// 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', home: new ComplexLayout() ); } bool _lightTheme = true; bool get lightTheme => _lightTheme; set lightTheme(bool value) { setState(() { _lightTheme = value; }); } void toggleAnimationSpeed() { setState(() { timeDilation = (timeDilation != 1.0) ? 1.0 : 5.0; }); } } 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 FancyItemDelegate extends LazyBlockDelegate { @override Widget buildItem(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")); } @override bool shouldRebuild(FancyItemDelegate oldDelegate) => false; } 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 LazyBlock( key: new Key("main-scroll"), delegate: new FancyItemDelegate() ) ), new BottomBar() ] ), drawer: new GalleryDrawer() ); } } class TopBarMenu extends StatelessWidget { @override Widget build(BuildContext context) { return new PopupMenuButton<String>( onSelected: (String value) { print("Selected: $value"); }, itemBuilder: (BuildContext context) => <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<String>( 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; } @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: () { ComplexLayoutApp.of(context).toggleAnimationSpeed(); }, child: new Row( children: <Widget>[ new Flexible(child: new Text('Animate Slowly')), new Checkbox( value: timeDilation != 1.0, onChanged: (bool value) { ComplexLayoutApp.of(context).toggleAnimationSpeed(); } ) ] ) ) ] ) ); } } class FancyDrawerHeader extends StatelessWidget { @override Widget build(BuildContext context) { return new Container( decoration: new BoxDecoration( backgroundColor: Colors.purple[500] ), height: 200.0 ); } }