Added button dialog and snackbar demos
This commit is contained in:
parent
c91ace827c
commit
4264d5e749
211
examples/material_gallery/lib/demo/buttons_demo.dart
Normal file
211
examples/material_gallery/lib/demo/buttons_demo.dart
Normal file
@ -0,0 +1,211 @@
|
||||
// Copyright 2016 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/widgets.dart';
|
||||
|
||||
import 'tabs_fab_demo.dart';
|
||||
import 'dialog_demo.dart';
|
||||
import 'snack_bar_demo.dart';
|
||||
|
||||
const String _floatingText =
|
||||
"A floating action button is a circular material button that lifts "
|
||||
"and displays an ink reaction on press. It turns and fades in when "
|
||||
"it changes.";
|
||||
|
||||
const String _raisedText =
|
||||
"A raised button is typically a rectangular material button that lifts "
|
||||
"and displays ink reactions on press. Raised buttons add dimension to "
|
||||
"mostly flat layouts. They emphasize functions on busy or wide spaces.";
|
||||
|
||||
const String _flatText =
|
||||
"A flat button is made of ink that displays ink reactions on press "
|
||||
"but does not lift. Use flat buttons on toolbars, in dialogs and "
|
||||
"inline with padding";
|
||||
|
||||
const String _dropdownText =
|
||||
"A dropdown button selects between multiple selections. The button "
|
||||
"displays the current state and a down arrow.";
|
||||
|
||||
class _ButtonDemo {
|
||||
_ButtonDemo({ this.title, this.text, this.builder }) {
|
||||
assert(title != null);
|
||||
assert(text != null);
|
||||
assert(builder != null);
|
||||
}
|
||||
|
||||
final String title;
|
||||
final String text;
|
||||
final WidgetBuilder builder;
|
||||
|
||||
TabLabel get tabLabel => new TabLabel(text: title.toUpperCase());
|
||||
|
||||
// The TabBarSelection created below saves and restores _ButtonDemo objects
|
||||
// to recover this demo's selected tab. To enable it to compare restored
|
||||
// _ButtonDemo objects with new ones, define hashCode and operator== .
|
||||
|
||||
bool operator==(Object other) {
|
||||
if (other.runtimeType != runtimeType)
|
||||
return false;
|
||||
_ButtonDemo typedOther = other;
|
||||
return typedOther.title == title && typedOther.text == text;
|
||||
}
|
||||
|
||||
int get hashCode => hashValues(title.hashCode, text.hashCode);
|
||||
}
|
||||
|
||||
class ButtonsDemo extends StatefulComponent {
|
||||
_ButtonsDemoState createState() => new _ButtonsDemoState();
|
||||
}
|
||||
|
||||
class _ButtonsDemoState extends State<ButtonsDemo> {
|
||||
List<_ButtonDemo> demos;
|
||||
|
||||
void initState() {
|
||||
super.initState();
|
||||
demos = <_ButtonDemo>[
|
||||
new _ButtonDemo(title: 'FLOATING', text: _floatingText, builder: buildFloatingButton),
|
||||
new _ButtonDemo(title: 'RAISED', text: _raisedText, builder: buildRaisedButton),
|
||||
new _ButtonDemo(title: 'FLAT', text: _flatText, builder: buildFlatButton),
|
||||
new _ButtonDemo(title: 'DROPDOWN', text: _dropdownText, builder: buildDropdownButton)
|
||||
];
|
||||
}
|
||||
|
||||
Widget buildFloatingButton(BuildContext context) {
|
||||
return new SizedBox(
|
||||
height: 128.0,
|
||||
child: new Center(
|
||||
child: new FloatingActionButton(
|
||||
child: new Icon(icon: 'content/add'),
|
||||
onPressed: () {
|
||||
Navigator.push(context, new MaterialPageRoute(builder: (_) => new TabsFabDemo()));
|
||||
}
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildRaisedButton(BuildContext context) {
|
||||
return new Container(
|
||||
margin: const EdgeDims.symmetric(vertical: 16.0),
|
||||
child: new Column(
|
||||
children: <Widget>[
|
||||
new RaisedButton(
|
||||
child: new Text("Launch Demo"),
|
||||
onPressed: () {
|
||||
Navigator.push(context, new MaterialPageRoute(builder: (_) => new SnackBarDemo()));
|
||||
}
|
||||
),
|
||||
new RaisedButton(
|
||||
child: new Text("Disabled")
|
||||
)
|
||||
]
|
||||
.map((Widget child) {
|
||||
return new Container(
|
||||
margin: const EdgeDims.symmetric(vertical: 8.0),
|
||||
child: child
|
||||
);
|
||||
})
|
||||
.toList()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildFlatButton(BuildContext context) {
|
||||
return new Container(
|
||||
margin: const EdgeDims.symmetric(vertical: 16.0),
|
||||
child: new ButtonTheme(
|
||||
color: ButtonColor.accent,
|
||||
child: new Column(
|
||||
children: <Widget>[
|
||||
new FlatButton(
|
||||
child: new Text("Launch Demo"),
|
||||
onPressed: () {
|
||||
showDialog(context: context, child: new DialogDemo()).then((String value) {
|
||||
if (value != null) {
|
||||
Scaffold.of(context).showSnackBar(new SnackBar(
|
||||
content: new Text('You dismissed the dialog with "$value"')
|
||||
));
|
||||
}
|
||||
});
|
||||
}
|
||||
),
|
||||
new FlatButton(
|
||||
child: new Text("Disabled")
|
||||
)
|
||||
]
|
||||
.map((Widget child) {
|
||||
return new Container(
|
||||
margin: const EdgeDims.symmetric(vertical: 8.0),
|
||||
child: child
|
||||
);
|
||||
})
|
||||
.toList()
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
String dropdownValue = "Free";
|
||||
|
||||
Widget buildDropdownButton(BuildContext context) {
|
||||
return new SizedBox(
|
||||
height: 256.0,
|
||||
child: new Center(
|
||||
child: new DropDownButton<String>(
|
||||
value: dropdownValue,
|
||||
onChanged: (String newValue) {
|
||||
setState(() {
|
||||
if (newValue != null)
|
||||
dropdownValue = newValue;
|
||||
});
|
||||
},
|
||||
items: <String>["One", "Two", "Free", "Four"]
|
||||
.map((String value) {
|
||||
return new DropDownMenuItem<String>(
|
||||
value: value,
|
||||
child: new Text(value));
|
||||
})
|
||||
.toList()
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildTabView(_ButtonDemo demo) {
|
||||
return new Builder(
|
||||
builder: (BuildContext context) {
|
||||
final TextStyle textStyle = Theme.of(context).text.caption.copyWith(fontSize: 16.0);
|
||||
return new Column(
|
||||
alignItems: FlexAlignItems.stretch,
|
||||
children: <Widget>[
|
||||
demo.builder(context),
|
||||
new Padding(
|
||||
padding: const EdgeDims.symmetric(horizontal: 32.0),
|
||||
child: new Text(demo.text, style: textStyle)
|
||||
)
|
||||
]
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
Widget build(BuildContext context) {
|
||||
return new TabBarSelection<_ButtonDemo>(
|
||||
values: demos,
|
||||
child: new Scaffold(
|
||||
toolBar: new ToolBar(
|
||||
center: new Text("Buttons"),
|
||||
tabBar: new TabBar<_ButtonDemo>(
|
||||
isScrollable: true,
|
||||
labels: new Map.fromIterable(demos, value: (_ButtonDemo demo) => demo.tabLabel)
|
||||
)
|
||||
),
|
||||
body: new TabBarView(
|
||||
children: demos.map(buildTabView).toList()
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
37
examples/material_gallery/lib/demo/dialog_demo.dart
Normal file
37
examples/material_gallery/lib/demo/dialog_demo.dart
Normal file
@ -0,0 +1,37 @@
|
||||
// Copyright 2016 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/widgets.dart';
|
||||
|
||||
const String _dialogText =
|
||||
"Use dialogs sparingly because they are interruptive. Their sudden appearance "
|
||||
"forces users to stop their current task and focus on the dialog content. "
|
||||
"Alternatives to dialogs include menus or inline expansion, both of which "
|
||||
"maintain the current context.";
|
||||
|
||||
class DialogDemo extends StatelessComponent {
|
||||
DialogDemo({ Key key }) : super(key: key);
|
||||
|
||||
Widget build(BuildContext context) {
|
||||
final ThemeData theme = Theme.of(context);
|
||||
return new Dialog(
|
||||
title: new Text("This is a Dialog"),
|
||||
content: new Text(
|
||||
_dialogText,
|
||||
style: theme.text.subhead.copyWith(color: theme.text.caption.color)
|
||||
),
|
||||
actions: <Widget>[
|
||||
new FlatButton(
|
||||
child: new Text("CANCEL"),
|
||||
onPressed: () { Navigator.pop(context, "CANCEL"); }
|
||||
),
|
||||
new FlatButton(
|
||||
child: new Text("OK"),
|
||||
onPressed: () { Navigator.pop(context, "OK"); }
|
||||
)
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
73
examples/material_gallery/lib/demo/snack_bar_demo.dart
Normal file
73
examples/material_gallery/lib/demo/snack_bar_demo.dart
Normal file
@ -0,0 +1,73 @@
|
||||
// Copyright 2016 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/widgets.dart';
|
||||
|
||||
const String _text1 =
|
||||
"Snackbars provide lightweight feedback about an operation by "
|
||||
"showing a brief message at the bottom of the screen. Snackbars "
|
||||
"can contain an action.";
|
||||
|
||||
const String _text2 =
|
||||
"Snackbars should contain a single line of text directly related "
|
||||
"to the operation performed. They cannot contain icons.";
|
||||
|
||||
const String _text3 =
|
||||
"By default snackbars automatically disappear after a few seconds ";
|
||||
|
||||
class SnackBarDemo extends StatelessComponent {
|
||||
SnackBarDemo({ Key key }) : super(key: key);
|
||||
|
||||
Widget buildBody(BuildContext context) {
|
||||
return new Padding(
|
||||
padding: const EdgeDims.all(24.0),
|
||||
child: new Column(
|
||||
children: <Widget>[
|
||||
new Text(_text1),
|
||||
new Text(_text2),
|
||||
new RaisedButton(
|
||||
child: new Text('Show a SnackBar'),
|
||||
onPressed: () {
|
||||
Scaffold.of(context).showSnackBar(new SnackBar(
|
||||
content: new Text('This is a SnackBar'),
|
||||
actions: <SnackBarAction>[
|
||||
new SnackBarAction(
|
||||
label: 'Action',
|
||||
onPressed: () {
|
||||
Scaffold.of(context).showSnackBar(new SnackBar(
|
||||
content: new Text("You pressed the SnackBar's Action")
|
||||
));
|
||||
}
|
||||
)
|
||||
]
|
||||
));
|
||||
}
|
||||
),
|
||||
new Text(_text3),
|
||||
]
|
||||
.map((Widget child) {
|
||||
return new Container(
|
||||
margin: const EdgeDims.symmetric(vertical: 12.0),
|
||||
child: child
|
||||
);
|
||||
})
|
||||
.toList()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
Widget build(BuildContext context) {
|
||||
return new Scaffold(
|
||||
toolBar: new ToolBar(
|
||||
center: new Text('SnackBar')
|
||||
),
|
||||
body: new Builder(
|
||||
// Create an inner BuildContext so that the snackBar onPressed methods
|
||||
// can refer to the Scaffold with Scaffold.of().
|
||||
builder: buildBody
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
@ -17,7 +17,7 @@ class TabsDemo extends StatelessComponent {
|
||||
isScrollable: true,
|
||||
labels: new Map.fromIterable(
|
||||
iconNames,
|
||||
value: (String iconName) => new TabLabel(text: iconName, icon: "action/$iconName")
|
||||
value: (String iconName) => new TabLabel(text: iconName.toUpperCase(), icon: "action/$iconName")
|
||||
)
|
||||
)
|
||||
),
|
||||
|
@ -11,7 +11,7 @@ class _Page {
|
||||
final Map<int, Color> colors;
|
||||
final String icon;
|
||||
|
||||
TabLabel get tabLabel => new TabLabel(text: label);
|
||||
TabLabel get tabLabel => new TabLabel(text: label.toUpperCase());
|
||||
Color get labelColor => colors != null ? colors[300] : Colors.grey[300];
|
||||
bool get fabDefined => colors != null && icon != null;
|
||||
Color get fabColor => colors[400];
|
||||
@ -31,7 +31,7 @@ class TabsFabDemo extends StatefulComponent {
|
||||
|
||||
class _TabsFabDemoState extends State<TabsFabDemo> {
|
||||
final GlobalKey scaffoldKey = new GlobalKey();
|
||||
final List<_Page> _pages = <_Page>[
|
||||
final List<_Page> pages = <_Page>[
|
||||
new _Page(label: 'Blue', colors: Colors.indigo, icon: 'content/add'),
|
||||
new _Page(label: 'Too', colors: Colors.indigo, icon: 'content/add'),
|
||||
new _Page(label: 'Eco', colors: Colors.green, icon: 'content/create'),
|
||||
@ -43,7 +43,7 @@ class _TabsFabDemoState extends State<TabsFabDemo> {
|
||||
|
||||
void initState() {
|
||||
super.initState();
|
||||
selectedPage = _pages[0];
|
||||
selectedPage = pages[0];
|
||||
}
|
||||
|
||||
void _handleTabSelection(_Page page) {
|
||||
@ -90,14 +90,14 @@ class _TabsFabDemoState extends State<TabsFabDemo> {
|
||||
|
||||
Widget build(BuildContext context) {
|
||||
return new TabBarSelection<_Page>(
|
||||
values: _pages,
|
||||
values: pages,
|
||||
onChanged: _handleTabSelection,
|
||||
child: new Scaffold(
|
||||
key: scaffoldKey,
|
||||
toolBar: new ToolBar(
|
||||
center: new Text("FAB per Tab"),
|
||||
tabBar: new TabBar<_Page>(
|
||||
labels: new Map.fromIterable(_pages, value: (_Page page) => page.tabLabel)
|
||||
labels: new Map.fromIterable(pages, value: (_Page page) => page.tabLabel)
|
||||
)
|
||||
),
|
||||
floatingActionButton: !selectedPage.fabDefined ? null : new FloatingActionButton(
|
||||
@ -106,7 +106,7 @@ class _TabsFabDemoState extends State<TabsFabDemo> {
|
||||
child: selectedPage.fabIcon,
|
||||
onPressed: _showExplanatoryText
|
||||
),
|
||||
body: new TabBarView(children: _pages.map(buildTabView).toList())
|
||||
body: new TabBarView(children: pages.map(buildTabView).toList())
|
||||
)
|
||||
);
|
||||
}
|
||||
|
35
examples/material_gallery/lib/gallery/app.dart
Normal file
35
examples/material_gallery/lib/gallery/app.dart
Normal file
@ -0,0 +1,35 @@
|
||||
// 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 'home.dart';
|
||||
|
||||
class GalleryApp extends StatefulComponent {
|
||||
GalleryApp({ Key key }) : super(key: key);
|
||||
|
||||
static GalleryAppState of(BuildContext context) => context.ancestorStateOfType(const TypeMatcher<GalleryAppState>());
|
||||
|
||||
GalleryAppState createState() => new GalleryAppState();
|
||||
}
|
||||
|
||||
class GalleryAppState extends State<GalleryApp> {
|
||||
bool _lightTheme = true;
|
||||
bool get lightTheme => _lightTheme;
|
||||
void set lightTheme(bool value) {
|
||||
setState(() {
|
||||
_lightTheme = value;
|
||||
});
|
||||
}
|
||||
|
||||
Widget build(BuildContext context) {
|
||||
return new MaterialApp(
|
||||
title: 'Flutter Material Gallery',
|
||||
theme: lightTheme ? new ThemeData.light() : new ThemeData.dark(),
|
||||
routes: {
|
||||
'/': (RouteArguments args) => new GalleryHome()
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
17
examples/material_gallery/lib/gallery/demo.dart
Normal file
17
examples/material_gallery/lib/gallery/demo.dart
Normal file
@ -0,0 +1,17 @@
|
||||
// Copyright 2016 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/widgets.dart';
|
||||
|
||||
typedef Widget GalleryDemoBuilder();
|
||||
|
||||
class GalleryDemo {
|
||||
GalleryDemo({ this.title, this.builder }) {
|
||||
assert(title != null);
|
||||
assert(builder != null);
|
||||
}
|
||||
|
||||
final String title;
|
||||
final GalleryDemoBuilder builder;
|
||||
}
|
78
examples/material_gallery/lib/gallery/drawer.dart
Normal file
78
examples/material_gallery/lib/gallery/drawer.dart
Normal file
@ -0,0 +1,78 @@
|
||||
// Copyright 2016 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;
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'app.dart';
|
||||
|
||||
class GalleryDrawer extends StatelessComponent {
|
||||
GalleryDrawer({ Key key }) : super(key: key);
|
||||
|
||||
void _changeTheme(BuildContext context, bool value) {
|
||||
GalleryApp.of(context).lightTheme = value;
|
||||
}
|
||||
|
||||
void _toggleAnimationSpeed(BuildContext context) {
|
||||
GalleryApp.of(context).setState(() {
|
||||
timeDilation = (timeDilation != 1.0) ? 1.0 : 5.0;
|
||||
});
|
||||
}
|
||||
|
||||
Widget build(BuildContext context) {
|
||||
return new Drawer(
|
||||
child: new Block(
|
||||
children: <Widget>[
|
||||
new DrawerHeader(child: new Text('Flutter Gallery')),
|
||||
new DrawerItem(
|
||||
icon: 'image/brightness_5',
|
||||
onPressed: () { _changeTheme(context, true); },
|
||||
selected: GalleryApp.of(context).lightTheme,
|
||||
child: new Row(
|
||||
children: <Widget>[
|
||||
new Flexible(child: new Text('Light')),
|
||||
new Radio<bool>(
|
||||
value: true,
|
||||
groupValue: GalleryApp.of(context).lightTheme,
|
||||
onChanged: (bool value) { _changeTheme(context, value); }
|
||||
)
|
||||
]
|
||||
)
|
||||
),
|
||||
new DrawerItem(
|
||||
icon: 'image/brightness_7',
|
||||
onPressed: () { _changeTheme(context, false); },
|
||||
selected: !GalleryApp.of(context).lightTheme,
|
||||
child: new Row(
|
||||
children: <Widget>[
|
||||
new Flexible(child: new Text('Dark')),
|
||||
new Radio<bool>(
|
||||
value: false,
|
||||
groupValue: GalleryApp.of(context).lightTheme,
|
||||
onChanged: (bool value) { _changeTheme(context, value); }
|
||||
)
|
||||
]
|
||||
)
|
||||
),
|
||||
new DrawerDivider(),
|
||||
new DrawerItem(
|
||||
icon: 'action/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); }
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
]
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
129
examples/material_gallery/lib/gallery/home.dart
Normal file
129
examples/material_gallery/lib/gallery/home.dart
Normal file
@ -0,0 +1,129 @@
|
||||
// Copyright 2016 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/widgets.dart';
|
||||
|
||||
import 'demo.dart';
|
||||
import 'drawer.dart';
|
||||
import 'section.dart';
|
||||
|
||||
import '../demo/buttons_demo.dart';
|
||||
import '../demo/chip_demo.dart';
|
||||
import '../demo/date_picker_demo.dart';
|
||||
import '../demo/dialog_demo.dart';
|
||||
import '../demo/drop_down_demo.dart';
|
||||
import '../demo/modal_bottom_sheet_demo.dart';
|
||||
import '../demo/page_selector_demo.dart';
|
||||
import '../demo/persistent_bottom_sheet_demo.dart';
|
||||
import '../demo/progress_indicator_demo.dart';
|
||||
import '../demo/toggle_controls_demo.dart';
|
||||
import '../demo/scrolling_techniques_demo.dart';
|
||||
import '../demo/slider_demo.dart';
|
||||
import '../demo/snack_bar_demo.dart';
|
||||
import '../demo/tabs_demo.dart';
|
||||
import '../demo/tabs_fab_demo.dart';
|
||||
import '../demo/time_picker_demo.dart';
|
||||
import '../demo/two_level_list_demo.dart';
|
||||
import '../demo/weathers_demo.dart';
|
||||
|
||||
class GalleryHome extends StatefulComponent {
|
||||
GalleryHome({ Key key }) : super(key: key);
|
||||
|
||||
GalleryHomeState createState() => new GalleryHomeState();
|
||||
}
|
||||
|
||||
class GalleryHomeState extends State<GalleryHome> {
|
||||
Widget build(BuildContext context) {
|
||||
return new Scaffold(
|
||||
appBarHeight: 128.0,
|
||||
drawer: new GalleryDrawer(),
|
||||
toolBar: new ToolBar(
|
||||
flexibleSpace: (BuildContext context) {
|
||||
return new Container(
|
||||
padding: const EdgeDims.only(left: 16.0, bottom: 24.0),
|
||||
height: 128.0,
|
||||
child: new Align(
|
||||
alignment: const FractionalOffset(0.0, 1.0),
|
||||
child: new Text('Flutter Gallery', style: Typography.white.headline)
|
||||
)
|
||||
);
|
||||
}
|
||||
),
|
||||
body: new Padding(
|
||||
padding: const EdgeDims.all(4.0),
|
||||
child: new Block(
|
||||
children: <Widget>[
|
||||
new Row(
|
||||
children: <Widget>[
|
||||
new GallerySection(
|
||||
title: 'Animation',
|
||||
image: 'assets/section_animation.png',
|
||||
colors: Colors.purple,
|
||||
demos: <GalleryDemo>[
|
||||
new GalleryDemo(title: 'Weathers', builder: () => new WeathersDemo())
|
||||
]
|
||||
),
|
||||
new GallerySection(
|
||||
title: 'Style',
|
||||
image: 'assets/section_style.png',
|
||||
colors: Colors.green
|
||||
)
|
||||
]
|
||||
),
|
||||
new Row(
|
||||
children: <Widget>[
|
||||
new GallerySection(
|
||||
title: 'Layout',
|
||||
image: 'assets/section_layout.png',
|
||||
colors: Colors.pink
|
||||
),
|
||||
new GallerySection(
|
||||
title: 'Components',
|
||||
image: 'assets/section_components.png',
|
||||
colors: Colors.amber,
|
||||
demos: <GalleryDemo>[
|
||||
new GalleryDemo(title: 'Buttons', builder: () => new ButtonsDemo()),
|
||||
new GalleryDemo(title: 'Chips', builder: () => new ChipDemo()),
|
||||
new GalleryDemo(title: 'Date Picker', builder: () => new DatePickerDemo()),
|
||||
new GalleryDemo(title: 'Dialog', builder: () => new DialogDemo()),
|
||||
new GalleryDemo(title: 'Dropdown Button', builder: () => new DropDownDemo()),
|
||||
new GalleryDemo(title: 'Expland/Collapse List Control', builder: () => new TwoLevelListDemo()),
|
||||
new GalleryDemo(title: 'Floating Action Button', builder: () => new TabsFabDemo()),
|
||||
new GalleryDemo(title: 'Modal Bottom Sheet', builder: () => new ModalBottomSheetDemo()),
|
||||
new GalleryDemo(title: 'Page Selector', builder: () => new PageSelectorDemo()),
|
||||
new GalleryDemo(title: 'Persistent Bottom Sheet', builder: () => new PersistentBottomSheetDemo()),
|
||||
new GalleryDemo(title: 'Progress Indicators', builder: () => new ProgressIndicatorDemo()),
|
||||
new GalleryDemo(title: 'Selection Controls', builder: () => new ToggleControlsDemo()),
|
||||
new GalleryDemo(title: 'Sliders', builder: () => new SliderDemo()),
|
||||
new GalleryDemo(title: 'SnackBar', builder: () => new SnackBarDemo()),
|
||||
new GalleryDemo(title: 'Tabs', builder: () => new TabsDemo()),
|
||||
new GalleryDemo(title: 'Time Picker', builder: () => new TimePickerDemo())
|
||||
]
|
||||
)
|
||||
]
|
||||
),
|
||||
new Row(
|
||||
children: <Widget>[
|
||||
new GallerySection(
|
||||
title: 'Patterns',
|
||||
image: 'assets/section_patterns.png',
|
||||
colors: Colors.cyan,
|
||||
demos: <GalleryDemo>[
|
||||
new GalleryDemo(title: 'Scrolling Techniques', builder: () => new ScrollingTechniquesDemo())
|
||||
]
|
||||
),
|
||||
new GallerySection(
|
||||
title: 'Usability',
|
||||
image: 'assets/section_usability.png',
|
||||
colors: Colors.lightGreen
|
||||
)
|
||||
]
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
105
examples/material_gallery/lib/gallery/section.dart
Normal file
105
examples/material_gallery/lib/gallery/section.dart
Normal file
@ -0,0 +1,105 @@
|
||||
// Copyright 2016 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/widgets.dart';
|
||||
|
||||
import 'demo.dart';
|
||||
|
||||
class GallerySection extends StatelessComponent {
|
||||
GallerySection({ this.title, this.image, this.colors, this.demos });
|
||||
|
||||
final String title;
|
||||
final String image;
|
||||
final Map<int, Color> colors;
|
||||
final List<GalleryDemo> demos;
|
||||
|
||||
void showDemo(GalleryDemo demo, BuildContext context, ThemeData theme) {
|
||||
Navigator.push(context, new MaterialPageRoute(
|
||||
builder: (BuildContext context) {
|
||||
Widget child = (demo.builder == null) ? null : demo.builder();
|
||||
return new Theme(data: theme, child: child);
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
void showDemos(BuildContext context) {
|
||||
final ThemeData theme = new ThemeData(
|
||||
brightness: Theme.of(context).brightness,
|
||||
primarySwatch: colors
|
||||
);
|
||||
final double appBarHeight = 200.0;
|
||||
final Key scrollableKey = new ValueKey<String>(title); // assume section titles differ
|
||||
Navigator.push(context, new MaterialPageRoute(
|
||||
builder: (BuildContext context) {
|
||||
return new Theme(
|
||||
data: theme,
|
||||
child: new Scaffold(
|
||||
appBarHeight: appBarHeight,
|
||||
appBarBehavior: AppBarBehavior.scroll,
|
||||
scrollableKey: scrollableKey,
|
||||
toolBar: new ToolBar(
|
||||
flexibleSpace: (BuildContext context) => new FlexibleSpaceBar(title: new Text(title))
|
||||
),
|
||||
body: new Material(
|
||||
child: new MaterialList(
|
||||
scrollableKey: scrollableKey,
|
||||
scrollablePadding: new EdgeDims.only(top: appBarHeight),
|
||||
type: MaterialListType.oneLine,
|
||||
children: (demos ?? const <GalleryDemo>[]).map((GalleryDemo demo) {
|
||||
return new ListItem(
|
||||
center: new Text(demo.title, style: theme.text.subhead),
|
||||
onTap: () { showDemo(demo, context, theme); }
|
||||
);
|
||||
})
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
Widget build (BuildContext context) {
|
||||
final ThemeData theme = new ThemeData(
|
||||
brightness: Theme.of(context).brightness,
|
||||
primarySwatch: colors
|
||||
);
|
||||
final TextStyle titleTextStyle = theme.text.title.copyWith(
|
||||
color: theme.brightness == ThemeBrightness.dark ? Colors.black : Colors.white
|
||||
);
|
||||
return new Flexible(
|
||||
child: new GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: () { showDemos(context); },
|
||||
child: new Container(
|
||||
height: 256.0,
|
||||
margin: const EdgeDims.all(4.0),
|
||||
decoration: new BoxDecoration(backgroundColor: theme.primaryColor),
|
||||
child: new Column(
|
||||
children: <Widget>[
|
||||
new Flexible(
|
||||
child: new Padding(
|
||||
padding: const EdgeDims.symmetric(horizontal: 12.0),
|
||||
child: new AssetImage(
|
||||
name: image,
|
||||
alignment: const FractionalOffset(0.5, 0.5),
|
||||
fit: ImageFit.contain
|
||||
)
|
||||
)
|
||||
),
|
||||
new Padding(
|
||||
padding: const EdgeDims.all(16.0),
|
||||
child: new Align(
|
||||
alignment: const FractionalOffset(0.0, 1.0),
|
||||
child: new Text(title, style: titleTextStyle)
|
||||
)
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
@ -2,312 +2,9 @@
|
||||
// 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;
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'demo/chip_demo.dart';
|
||||
import 'demo/date_picker_demo.dart';
|
||||
import 'demo/drop_down_demo.dart';
|
||||
import 'demo/modal_bottom_sheet_demo.dart';
|
||||
import 'demo/page_selector_demo.dart';
|
||||
import 'demo/persistent_bottom_sheet_demo.dart';
|
||||
import 'demo/progress_indicator_demo.dart';
|
||||
import 'demo/toggle_controls_demo.dart';
|
||||
import 'demo/scrolling_techniques_demo.dart';
|
||||
import 'demo/slider_demo.dart';
|
||||
import 'demo/tabs_demo.dart';
|
||||
import 'demo/tabs_fab_demo.dart';
|
||||
import 'demo/time_picker_demo.dart';
|
||||
import 'demo/two_level_list_demo.dart';
|
||||
import 'demo/weathers_demo.dart';
|
||||
|
||||
typedef Widget GalleryDemoBuilder();
|
||||
|
||||
class GalleryDemo {
|
||||
GalleryDemo({ this.title, this.builder });
|
||||
|
||||
final String title;
|
||||
final GalleryDemoBuilder builder;
|
||||
}
|
||||
|
||||
class GallerySection extends StatelessComponent {
|
||||
GallerySection({ this.title, this.image, this.colors, this.demos });
|
||||
|
||||
final String title;
|
||||
final String image;
|
||||
final Map<int, Color> colors;
|
||||
final List<GalleryDemo> demos;
|
||||
|
||||
void showDemo(GalleryDemo demo, BuildContext context, ThemeData theme) {
|
||||
Navigator.push(context, new MaterialPageRoute(
|
||||
builder: (BuildContext context) {
|
||||
Widget child = (demo.builder == null) ? null : demo.builder();
|
||||
return new Theme(data: theme, child: child);
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
void showDemos(BuildContext context) {
|
||||
final theme = new ThemeData(
|
||||
brightness: Theme.of(context).brightness,
|
||||
primarySwatch: colors
|
||||
);
|
||||
final appBarHeight = 200.0;
|
||||
final scrollableKey = new ValueKey<String>(title); // assume section titles differ
|
||||
Navigator.push(context, new MaterialPageRoute(
|
||||
builder: (BuildContext context) {
|
||||
return new Theme(
|
||||
data: theme,
|
||||
child: new Scaffold(
|
||||
appBarHeight: appBarHeight,
|
||||
appBarBehavior: AppBarBehavior.scroll,
|
||||
scrollableKey: scrollableKey,
|
||||
toolBar: new ToolBar(
|
||||
flexibleSpace: (BuildContext context) => new FlexibleSpaceBar(title: new Text(title))
|
||||
),
|
||||
body: new Material(
|
||||
child: new MaterialList(
|
||||
scrollableKey: scrollableKey,
|
||||
scrollablePadding: new EdgeDims.only(top: appBarHeight),
|
||||
type: MaterialListType.oneLine,
|
||||
children: (demos ?? <GalleryDemo>[]).map((GalleryDemo demo) {
|
||||
return new ListItem(
|
||||
center: new Text(demo.title, style: theme.text.subhead),
|
||||
onTap: () { showDemo(demo, context, theme); }
|
||||
);
|
||||
})
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
Widget build (BuildContext context) {
|
||||
final theme = new ThemeData(
|
||||
brightness: Theme.of(context).brightness,
|
||||
primarySwatch: colors
|
||||
);
|
||||
final titleTextStyle = theme.text.title.copyWith(
|
||||
color: theme.brightness == ThemeBrightness.dark ? Colors.black : Colors.white
|
||||
);
|
||||
return new Flexible(
|
||||
child: new GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: () { showDemos(context); },
|
||||
child: new Container(
|
||||
height: 256.0,
|
||||
margin: const EdgeDims.all(4.0),
|
||||
decoration: new BoxDecoration(backgroundColor: theme.primaryColor),
|
||||
child: new Column(
|
||||
children: <Widget>[
|
||||
new Flexible(
|
||||
child: new Padding(
|
||||
padding: const EdgeDims.symmetric(horizontal: 12.0),
|
||||
child: new AssetImage(
|
||||
name: image,
|
||||
alignment: const FractionalOffset(0.5, 0.5),
|
||||
fit: ImageFit.contain
|
||||
)
|
||||
)
|
||||
),
|
||||
new Padding(
|
||||
padding: const EdgeDims.all(16.0),
|
||||
child: new Align(
|
||||
alignment: const FractionalOffset(0.0, 1.0),
|
||||
child: new Text(title, style: titleTextStyle)
|
||||
)
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class GalleryHome extends StatefulComponent {
|
||||
GalleryHomeState createState() => new GalleryHomeState();
|
||||
}
|
||||
|
||||
class GalleryHomeState extends State<GalleryHome> {
|
||||
void _changeTheme(BuildContext context, bool value) {
|
||||
GalleryApp.of(context).lightTheme = value;
|
||||
}
|
||||
|
||||
void _toggleAnimationSpeed() {
|
||||
setState((){
|
||||
timeDilation = (timeDilation != 1.0) ? 1.0 : 5.0;
|
||||
});
|
||||
}
|
||||
|
||||
Widget build(BuildContext context) {
|
||||
return new Scaffold(
|
||||
appBarHeight: 128.0,
|
||||
toolBar: new ToolBar(
|
||||
flexibleSpace: (BuildContext context) {
|
||||
return new Container(
|
||||
padding: const EdgeDims.only(left: 16.0, bottom: 24.0),
|
||||
height: 128.0,
|
||||
child: new Align(
|
||||
alignment: const FractionalOffset(0.0, 1.0),
|
||||
child: new Text('Flutter Gallery', style: Typography.white.headline)
|
||||
)
|
||||
);
|
||||
}
|
||||
),
|
||||
drawer: new Drawer(
|
||||
child: new Block(
|
||||
children: <Widget>[
|
||||
new DrawerHeader(child: new Text('Flutter Gallery')),
|
||||
new DrawerItem(
|
||||
icon: 'image/brightness_5',
|
||||
onPressed: () { _changeTheme(context, true); },
|
||||
selected: GalleryApp.of(context).lightTheme,
|
||||
child: new Row(
|
||||
children: <Widget>[
|
||||
new Flexible(child: new Text('Light')),
|
||||
new Radio<bool>(
|
||||
value: true,
|
||||
groupValue: GalleryApp.of(context).lightTheme,
|
||||
onChanged: (bool value) { _changeTheme(context, value); }
|
||||
)
|
||||
]
|
||||
)
|
||||
),
|
||||
new DrawerItem(
|
||||
icon: 'image/brightness_7',
|
||||
onPressed: () { _changeTheme(context, false); },
|
||||
selected: !GalleryApp.of(context).lightTheme,
|
||||
child: new Row(
|
||||
children: <Widget>[
|
||||
new Flexible(child: new Text('Dark')),
|
||||
new Radio<bool>(
|
||||
value: false,
|
||||
groupValue: GalleryApp.of(context).lightTheme,
|
||||
onChanged: (bool value) { _changeTheme(context, value); }
|
||||
)
|
||||
]
|
||||
)
|
||||
),
|
||||
new DrawerDivider(),
|
||||
new DrawerItem(
|
||||
icon: 'action/hourglass_empty',
|
||||
selected: timeDilation != 1.0,
|
||||
onPressed: () { _toggleAnimationSpeed(); },
|
||||
child: new Row(
|
||||
children: <Widget>[
|
||||
new Flexible(child: new Text('Animate Slowly')),
|
||||
new Checkbox(
|
||||
value: timeDilation != 1.0,
|
||||
onChanged: (bool value) { _toggleAnimationSpeed(); }
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
]
|
||||
)
|
||||
),
|
||||
body: new Padding(
|
||||
padding: const EdgeDims.all(4.0),
|
||||
child: new Block(
|
||||
children: <Widget>[
|
||||
new Row(
|
||||
children: <Widget>[
|
||||
new GallerySection(
|
||||
title: 'Animation',
|
||||
image: 'assets/section_animation.png',
|
||||
colors: Colors.purple,
|
||||
demos: <GalleryDemo>[
|
||||
new GalleryDemo(title: 'Weathers', builder: () => new WeathersDemo())
|
||||
]
|
||||
),
|
||||
new GallerySection(
|
||||
title: 'Style',
|
||||
image: 'assets/section_style.png',
|
||||
colors: Colors.green
|
||||
)
|
||||
]
|
||||
),
|
||||
new Row(
|
||||
children: <Widget>[
|
||||
new GallerySection(
|
||||
title: 'Layout',
|
||||
image: 'assets/section_layout.png',
|
||||
colors: Colors.pink
|
||||
),
|
||||
new GallerySection(
|
||||
title: 'Components',
|
||||
image: 'assets/section_components.png',
|
||||
colors: Colors.amber,
|
||||
demos: <GalleryDemo>[
|
||||
new GalleryDemo(title: 'Chips', builder: () => new ChipDemo()),
|
||||
new GalleryDemo(title: 'Date Picker', builder: () => new DatePickerDemo()),
|
||||
new GalleryDemo(title: 'Dropdown Button', builder: () => new DropDownDemo()),
|
||||
new GalleryDemo(title: 'Expland/Collapse List Control', builder: () => new TwoLevelListDemo()),
|
||||
new GalleryDemo(title: 'Floating Action Button', builder: () => new TabsFabDemo()),
|
||||
new GalleryDemo(title: 'Modal Bottom Sheet', builder: () => new ModalBottomSheetDemo()),
|
||||
new GalleryDemo(title: 'Page Selector', builder: () => new PageSelectorDemo()),
|
||||
new GalleryDemo(title: 'Persistent Bottom Sheet', builder: () => new PersistentBottomSheetDemo()),
|
||||
new GalleryDemo(title: 'Progress Indicators', builder: () => new ProgressIndicatorDemo()),
|
||||
new GalleryDemo(title: 'Selection Controls', builder: () => new ToggleControlsDemo()),
|
||||
new GalleryDemo(title: 'Sliders', builder: () => new SliderDemo()),
|
||||
new GalleryDemo(title: 'Tabs', builder: () => new TabsDemo()),
|
||||
new GalleryDemo(title: 'Time Picker', builder: () => new TimePickerDemo())
|
||||
]
|
||||
)
|
||||
]
|
||||
),
|
||||
new Row(
|
||||
children: <Widget>[
|
||||
new GallerySection(
|
||||
title: 'Patterns',
|
||||
image: 'assets/section_patterns.png',
|
||||
colors: Colors.cyan,
|
||||
demos: <GalleryDemo>[
|
||||
new GalleryDemo(title: 'Scrolling Techniques', builder: () => new ScrollingTechniquesDemo())
|
||||
]
|
||||
),
|
||||
new GallerySection(
|
||||
title: 'Usability',
|
||||
image: 'assets/section_usability.png',
|
||||
colors: Colors.lightGreen
|
||||
)
|
||||
]
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class GalleryApp extends StatefulComponent {
|
||||
static GalleryAppState of(BuildContext context) => context.ancestorStateOfType(const TypeMatcher<GalleryAppState>());
|
||||
|
||||
GalleryAppState createState() => new GalleryAppState();
|
||||
}
|
||||
|
||||
class GalleryAppState extends State<GalleryApp> {
|
||||
bool _lightTheme = true;
|
||||
bool get lightTheme => _lightTheme;
|
||||
void set lightTheme(bool value) {
|
||||
setState(() {
|
||||
_lightTheme = value;
|
||||
});
|
||||
}
|
||||
|
||||
Widget build(BuildContext context) {
|
||||
return new MaterialApp(
|
||||
title: 'Flutter Material Gallery',
|
||||
theme: lightTheme ? new ThemeData.light() : new ThemeData.dark(),
|
||||
routes: {
|
||||
'/': (RouteArguments args) => new GalleryHome()
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
import 'gallery/app.dart';
|
||||
|
||||
void main() {
|
||||
runApp(new GalleryApp());
|
||||
|
@ -134,7 +134,8 @@ abstract class MaterialButtonState<T extends MaterialButton> extends State<T> {
|
||||
return new Container(
|
||||
height: 36.0,
|
||||
constraints: new BoxConstraints(minWidth: 88.0),
|
||||
margin: new EdgeDims.all(8.0),
|
||||
padding: const EdgeDims.symmetric(horizontal: 8.0),
|
||||
margin: const EdgeDims.all(8.0),
|
||||
child: contents
|
||||
);
|
||||
}
|
||||
|
@ -436,6 +436,12 @@ class TabBarSelectionState<T> extends State<TabBarSelection<T>> {
|
||||
void initState() {
|
||||
super.initState();
|
||||
_value = config.value ?? PageStorage.of(context)?.readState(context) ?? values.first;
|
||||
|
||||
// If the selection's values have changed since the selected value was saved with
|
||||
// PageStorage.writeState() then use the default.
|
||||
if (!values.contains(_value))
|
||||
_value = values.first;
|
||||
|
||||
_previousValue = _value;
|
||||
_initValueToIndex();
|
||||
}
|
||||
@ -870,6 +876,7 @@ class _TabBarViewState extends PageableListState<TabBarView> implements TabBarSe
|
||||
void _updateItemsAndScrollBehavior() {
|
||||
assert(_selection != null);
|
||||
final int selectedIndex = _selection.index;
|
||||
assert(selectedIndex != null);
|
||||
_updateItemsForSelectedIndex(selectedIndex);
|
||||
_updateScrollBehaviorForSelectedIndex(selectedIndex);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user