mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00

It's safe to remove the unneeded `void`s from setters since the blocking issues in the `always_declare_return_types` lint have been fixed (https://github.com/dart-lang/linter/). We can also safely flip the bit on `avoid_return_types_on_setters`.
643 lines
19 KiB
Dart
643 lines
19 KiB
Dart
// 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;
|
|
});
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
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
|
|
);
|
|
}
|
|
}
|