| // Copyright 2015 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import 'package:flutter/material.dart'; |
| import 'package:flutter/scheduler.dart' show timeDilation; |
| |
| void main() { |
| runApp( |
| new ComplexLayoutApp() |
| ); |
| } |
| |
| class ComplexLayoutApp extends StatefulWidget { |
| @override |
| ComplexLayoutAppState createState() => new ComplexLayoutAppState(); |
| |
| static ComplexLayoutAppState of(BuildContext context) => context.ancestorStateOfType(const TypeMatcher<ComplexLayoutAppState>()); |
| } |
| |
| class ComplexLayoutAppState extends State<ComplexLayoutApp> { |
| @override |
| Widget build(BuildContext context) { |
| return new MaterialApp( |
| theme: lightTheme ? new ThemeData.light() : new ThemeData.dark(), |
| title: 'Advanced Layout', |
| routes: <String, WidgetBuilder>{ |
| '/': (BuildContext context) => new ComplexLayout(), |
| } |
| ); |
| } |
| |
| bool _lightTheme = true; |
| bool get lightTheme => _lightTheme; |
| void set lightTheme(bool value) { |
| setState(() { |
| _lightTheme = value; |
| }); |
| } |
| } |
| |
| class ComplexLayout extends StatefulWidget { |
| ComplexLayout({ Key key }) : super(key: key); |
| |
| @override |
| ComplexLayoutState createState() => new ComplexLayoutState(); |
| |
| static ComplexLayoutState of(BuildContext context) => context.ancestorStateOfType(const TypeMatcher<ComplexLayoutState>()); |
| |
| } |
| |
| class ComplexLayoutState extends State<ComplexLayout> { |
| @override |
| Widget build(BuildContext context) { |
| |
| return new Scaffold( |
| appBar: new AppBar( |
| title: new Text('Advanced Layout'), |
| actions: <Widget>[ |
| new IconButton( |
| icon: Icons.create, |
| tooltip: 'Search', |
| onPressed: () { |
| print("Pressed search"); |
| } |
| ), |
| new TopBarMenu() |
| ] |
| ), |
| body: new Column( |
| children: <Widget>[ |
| new Flexible( |
| child: new ScrollableMixedWidgetList( |
| key: new Key("main-scroll"), |
| builder: (BuildContext context, int index) { |
| if (index % 2 == 0) |
| return new FancyImageItem(index, key: new Key("Item $index")); |
| else |
| return new FancyGalleryItem(index, key: new Key("Item $index")); |
| } |
| ) |
| ), |
| new BottomBar() |
| ] |
| ), |
| drawer: new GalleryDrawer() |
| ); |
| } |
| } |
| |
| class TopBarMenu extends StatelessWidget { |
| @override |
| Widget build(BuildContext context) { |
| return new PopupMenuButton<String>( |
| onSelected: (String value) { print("Selected: $value"); }, |
| items: <PopupMenuItem<String>>[ |
| new PopupMenuItem<String>( |
| value: "Friends", |
| child: new MenuItemWithIcon(Icons.people, "Friends", "5 new") |
| ), |
| new PopupMenuItem<String>( |
| value: "Events", |
| child: new MenuItemWithIcon(Icons.event, "Events", "12 upcoming") |
| ), |
| new PopupMenuItem<String>( |
| value: "Events", |
| child: new MenuItemWithIcon(Icons.group, "Groups", "14") |
| ), |
| new PopupMenuItem<String>( |
| value: "Events", |
| child: new MenuItemWithIcon(Icons.image, "Pictures", "12") |
| ), |
| new PopupMenuItem<String>( |
| value: "Events", |
| child: new MenuItemWithIcon(Icons.near_me, "Nearby", "33") |
| ), |
| new PopupMenuItem<String>( |
| value: "Friends", |
| child: new MenuItemWithIcon(Icons.people, "Friends", "5") |
| ), |
| new PopupMenuItem<String>( |
| value: "Events", |
| child: new MenuItemWithIcon(Icons.event, "Events", "12") |
| ), |
| new PopupMenuItem<String>( |
| value: "Events", |
| child: new MenuItemWithIcon(Icons.group, "Groups", "14") |
| ), |
| new PopupMenuItem<String>( |
| value: "Events", |
| child: new MenuItemWithIcon(Icons.image, "Pictures", "12") |
| ), |
| new PopupMenuItem<String>( |
| value: "Events", |
| child: new MenuItemWithIcon(Icons.near_me, "Nearby", "33") |
| ) |
| ] |
| ); |
| } |
| } |
| |
| class MenuItemWithIcon extends StatelessWidget { |
| MenuItemWithIcon(this.icon, this.title, this.subtitle); |
| |
| final IconData icon; |
| final String title; |
| final String subtitle; |
| |
| @override |
| Widget build(BuildContext context) { |
| return new Row( |
| children: <Widget>[ |
| new Icon(icon: icon), |
| new Padding( |
| padding: new EdgeInsets.only(left: 8.0, right: 8.0), |
| child: new Text(title) |
| ), |
| new Text(subtitle, style: Theme.of(context).textTheme.caption) |
| ] |
| ); |
| } |
| } |
| |
| class FancyImageItem extends StatelessWidget { |
| FancyImageItem(this.index, {Key key}) : super(key: key); |
| |
| final int index; |
| |
| @override |
| Widget build(BuildContext context) { |
| return new BlockBody( |
| children: <Widget>[ |
| new UserHeader("Ali Connors $index"), |
| new ItemDescription(), |
| new ItemImageBox(), |
| new InfoBar(), |
| new Padding( |
| padding: new EdgeInsets.symmetric(horizontal: 8.0), |
| child: new Divider() |
| ), |
| new IconBar(), |
| new FatDivider() |
| ] |
| ); |
| } |
| } |
| |
| class FancyGalleryItem extends StatelessWidget { |
| FancyGalleryItem(this.index, {Key key}) : super(key: key); |
| |
| final int index; |
| @override |
| Widget build(BuildContext context) { |
| return new BlockBody( |
| children: <Widget>[ |
| new UserHeader("Ali Connors"), |
| new ItemGalleryBox(index), |
| new InfoBar(), |
| new Padding( |
| padding: new EdgeInsets.symmetric(horizontal: 8.0), |
| child: new Divider() |
| ), |
| new IconBar(), |
| new FatDivider() |
| ] |
| ); |
| } |
| } |
| |
| class InfoBar extends StatelessWidget { |
| @override |
| Widget build(BuildContext context) { |
| return new Padding( |
| padding: new EdgeInsets.all(8.0), |
| child: new Row( |
| mainAxisAlignment: MainAxisAlignment.spaceBetween, |
| children: <Widget>[ |
| new MiniIconWithText(Icons.thumb_up, "42"), |
| new Text("3 Comments", style: Theme.of(context).textTheme.caption) |
| ] |
| ) |
| ); |
| } |
| } |
| |
| class IconBar extends StatelessWidget { |
| @override |
| Widget build(BuildContext context) { |
| return new Padding( |
| padding: new EdgeInsets.only(left: 16.0, right: 16.0), |
| child: new Row( |
| mainAxisAlignment: MainAxisAlignment.spaceBetween, |
| children: <Widget>[ |
| new IconWithText(Icons.thumb_up, "Like"), |
| new IconWithText(Icons.comment, "Comment"), |
| new IconWithText(Icons.share, "Share"), |
| ] |
| ) |
| ); |
| } |
| } |
| |
| class IconWithText extends StatelessWidget { |
| IconWithText(this.icon, this.title); |
| |
| final IconData icon; |
| final String title; |
| |
| @override |
| Widget build(BuildContext context) { |
| return new Row( |
| mainAxisAlignment: MainAxisAlignment.collapse, |
| children: <Widget>[ |
| new IconButton(icon: icon, onPressed: () { print("Pressed $title button"); } ), |
| new Text(title) |
| ] |
| ); |
| } |
| } |
| |
| class MiniIconWithText extends StatelessWidget { |
| MiniIconWithText(this.icon, this.title); |
| |
| final IconData icon; |
| final String title; |
| |
| @override |
| Widget build(BuildContext context) { |
| return new Row( |
| mainAxisAlignment: MainAxisAlignment.collapse, |
| children: <Widget>[ |
| new Padding( |
| padding: new EdgeInsets.only(right: 8.0), |
| child: new Container( |
| width: 16.0, |
| height: 16.0, |
| decoration: new BoxDecoration( |
| backgroundColor: Theme.of(context).primaryColor, |
| shape: BoxShape.circle |
| ), |
| child: new Icon(icon: icon, color: Colors.white, size: 12.0) |
| ) |
| ), |
| new Text(title, style: Theme.of(context).textTheme.caption) |
| ] |
| ); |
| } |
| } |
| |
| class FatDivider extends StatelessWidget { |
| @override |
| Widget build(BuildContext context) { |
| return new Container( |
| height: 8.0, |
| decoration: new BoxDecoration( |
| backgroundColor: Theme.of(context).dividerColor |
| ) |
| ); |
| } |
| } |
| |
| class UserHeader extends StatelessWidget { |
| UserHeader(this.userName); |
| |
| final String userName; |
| |
| @override |
| Widget build(BuildContext context) { |
| return new Padding( |
| padding: new EdgeInsets.all(8.0), |
| child: new Row( |
| crossAxisAlignment: CrossAxisAlignment.start, |
| children: <Widget>[ |
| new Padding( |
| padding: new EdgeInsets.only(right: 8.0), |
| child: new AssetImage( |
| name: "packages/flutter_gallery_assets/ali_connors_sml.png", |
| width: 32.0, |
| height: 32.0 |
| ) |
| ), |
| new Flexible( |
| child: new Column( |
| mainAxisAlignment: MainAxisAlignment.start, |
| crossAxisAlignment: CrossAxisAlignment.stretch, |
| children: <Widget>[ |
| new RichText(text: new TextSpan( |
| style: Theme.of(context).textTheme.body1, |
| children: <TextSpan>[ |
| new TextSpan(text: userName, style: new TextStyle(fontWeight: FontWeight.bold)), |
| new TextSpan(text: " shared a new "), |
| new TextSpan(text: "photo", style: new TextStyle(fontWeight: FontWeight.bold)) |
| ] |
| )), |
| new Row( |
| children: <Widget>[ |
| new Text("Yesterday at 11:55 • ", style: Theme.of(context).textTheme.caption), |
| new Icon(icon: Icons.people, size: 16.0, color: Theme.of(context).textTheme.caption.color) |
| ] |
| ) |
| ] |
| ) |
| ), |
| new TopBarMenu() |
| ] |
| ) |
| ); |
| } |
| } |
| |
| class ItemDescription extends StatelessWidget { |
| @override |
| Widget build(BuildContext context) { |
| return new Padding( |
| padding: new EdgeInsets.all(8.0), |
| child: new Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.") |
| ); |
| } |
| } |
| |
| class ItemImageBox extends StatelessWidget { |
| @override |
| Widget build(BuildContext context) { |
| return new Padding( |
| padding: new EdgeInsets.all(8.0), |
| child: new Card( |
| child: new Column( |
| crossAxisAlignment: CrossAxisAlignment.stretch, |
| children: <Widget>[ |
| new Stack( |
| children: <Widget>[ |
| new SizedBox( |
| height: 230.0, |
| child: new AssetImage( |
| name: "packages/flutter_gallery_assets/top_10_australian_beaches.png" |
| ) |
| ), |
| new Theme( |
| data: new ThemeData.dark(), |
| child: new Row( |
| mainAxisAlignment: MainAxisAlignment.end, |
| children: <Widget>[ |
| new IconButton(icon: Icons.edit, onPressed: () { print("Pressed edit button"); }), |
| new IconButton(icon: Icons.zoom_in, onPressed: () { print("Pressed zoom button"); }) |
| ] |
| ) |
| ), |
| new Positioned( |
| bottom: 4.0, |
| left: 4.0, |
| child: new Container( |
| decoration: new BoxDecoration( |
| backgroundColor: Colors.black54, |
| borderRadius: 2.0 |
| ), |
| padding: new EdgeInsets.all(4.0), |
| child: new RichText( |
| text: new TextSpan( |
| style: new TextStyle(color: Colors.white), |
| children: <TextSpan>[ |
| new TextSpan( |
| text: "Photo by " |
| ), |
| new TextSpan( |
| style: new TextStyle(fontWeight: FontWeight.bold), |
| text: "Magic Mike" |
| ) |
| ] |
| ) |
| ) |
| ) |
| ) |
| ] |
| ) |
| , |
| new Padding( |
| padding: new EdgeInsets.all(8.0), |
| child: new Column( |
| crossAxisAlignment: CrossAxisAlignment.stretch, |
| children: <Widget>[ |
| new Text("Where can you find that amazing sunset?", style: Theme.of(context).textTheme.body2), |
| new Text("The sun sets over stinson beach", style: Theme.of(context).textTheme.body1), |
| new Text("flutter.io/amazingsunsets", style: Theme.of(context).textTheme.caption) |
| ] |
| ) |
| ) |
| ] |
| ) |
| ) |
| ); |
| } |
| } |
| |
| class ItemGalleryBox extends StatelessWidget { |
| ItemGalleryBox(this.index); |
| |
| final int index; |
| |
| @override |
| Widget build(BuildContext context) { |
| List<String> tabNames = <String>[ |
| "A", "B", "C", "D" |
| ]; |
| |
| return new SizedBox( |
| height: 200.0, |
| child: new TabBarSelection<String>( |
| values: tabNames, |
| child: new Column( |
| children: <Widget>[ |
| new Flexible( |
| child: new TabBarView( |
| children: tabNames.map((String tabName) { |
| return new Container( |
| key: new Key("Tab $index - $tabName"), |
| child: new Padding( |
| padding: new EdgeInsets.all(8.0), |
| child: new Card( |
| child: new Column( |
| children: <Widget>[ |
| new Flexible( |
| child: new Container( |
| decoration: new BoxDecoration( |
| backgroundColor: Theme.of(context).primaryColor |
| ), |
| child: new Center( |
| child: new Text(tabName, style: Theme.of(context).textTheme.headline.copyWith(color: Colors.white)) |
| ) |
| ) |
| ), |
| new Row( |
| children: <Widget>[ |
| new IconButton( |
| icon: Icons.share, |
| onPressed: () { print("Pressed share"); } |
| ), |
| new IconButton( |
| icon: Icons.event, |
| onPressed: () { print("Pressed event"); } |
| ), |
| new Flexible( |
| child: new Padding( |
| padding: new EdgeInsets.only(left: 8.0), |
| child: new Text("This is item $tabName") |
| ) |
| ) |
| ] |
| ) |
| ] |
| ) |
| ) |
| ) |
| ); |
| }).toList() |
| ) |
| ), |
| new Container( |
| child: new TabPageSelector<String>() |
| ) |
| ] |
| ) |
| ) |
| ); |
| } |
| } |
| |
| class BottomBar extends StatelessWidget { |
| @override |
| Widget build(BuildContext context) { |
| return new Container( |
| decoration: new BoxDecoration( |
| border: new Border( |
| top: new BorderSide( |
| color: Theme.of(context).dividerColor, |
| width: 1.0 |
| ) |
| ) |
| ), |
| child: new Row( |
| mainAxisAlignment: MainAxisAlignment.spaceBetween, |
| children: <Widget>[ |
| new BottomBarButton(Icons.new_releases, "News"), |
| new BottomBarButton(Icons.people, "Requests"), |
| new BottomBarButton(Icons.chat, "Messenger"), |
| new BottomBarButton(Icons.bookmark, "Bookmark"), |
| new BottomBarButton(Icons.alarm, "Alarm") |
| ] |
| ) |
| ); |
| } |
| } |
| |
| class BottomBarButton extends StatelessWidget { |
| BottomBarButton(this.icon, this.title); |
| |
| final IconData icon; |
| final String title; |
| |
| @override |
| Widget build(BuildContext context) { |
| return new Padding( |
| padding: new EdgeInsets.all(8.0), |
| child: new Column( |
| children: <Widget>[ |
| new IconButton( |
| icon: icon, |
| onPressed: () { print("Pressed: $title"); } |
| ), |
| new Text(title, style: Theme.of(context).textTheme.caption) |
| ] |
| ) |
| ); |
| } |
| } |
| |
| class GalleryDrawer extends StatelessWidget { |
| GalleryDrawer({ Key key }) : super(key: key); |
| |
| void _changeTheme(BuildContext context, bool value) { |
| ComplexLayoutApp.of(context).lightTheme = value; |
| } |
| |
| void _toggleAnimationSpeed(BuildContext context) { |
| ComplexLayoutApp.of(context).setState(() { |
| timeDilation = (timeDilation != 1.0) ? 1.0 : 5.0; |
| }); |
| } |
| |
| @override |
| Widget build(BuildContext context) { |
| return new Drawer( |
| child: new Block( |
| children: <Widget>[ |
| new FancyDrawerHeader(), |
| new DrawerItem( |
| icon: Icons.brightness_5, |
| onPressed: () { _changeTheme(context, true); }, |
| selected: ComplexLayoutApp.of(context).lightTheme, |
| child: new Row( |
| children: <Widget>[ |
| new Flexible(child: new Text('Light')), |
| new Radio<bool>( |
| value: true, |
| groupValue: ComplexLayoutApp.of(context).lightTheme, |
| onChanged: (bool value) { _changeTheme(context, value); } |
| ) |
| ] |
| ) |
| ), |
| new DrawerItem( |
| icon: Icons.brightness_7, |
| onPressed: () { _changeTheme(context, false); }, |
| selected: !ComplexLayoutApp.of(context).lightTheme, |
| child: new Row( |
| children: <Widget>[ |
| new Flexible(child: new Text('Dark')), |
| new Radio<bool>( |
| value: false, |
| groupValue: ComplexLayoutApp.of(context).lightTheme, |
| onChanged: (bool value) { _changeTheme(context, value); } |
| ) |
| ] |
| ) |
| ), |
| new Divider(), |
| new DrawerItem( |
| icon: Icons.hourglass_empty, |
| selected: timeDilation != 1.0, |
| onPressed: () { _toggleAnimationSpeed(context); }, |
| child: new Row( |
| children: <Widget>[ |
| new Flexible(child: new Text('Animate Slowly')), |
| new Checkbox( |
| value: timeDilation != 1.0, |
| onChanged: (bool value) { _toggleAnimationSpeed(context); } |
| ) |
| ] |
| ) |
| ) |
| ] |
| ) |
| ); |
| } |
| } |
| |
| class FancyDrawerHeader extends StatelessWidget { |
| @override |
| Widget build(BuildContext context) { |
| return new Container( |
| decoration: new BoxDecoration( |
| backgroundColor: Colors.purple[500] |
| ), |
| height: 200.0 |
| ); |
| } |
| } |