Commit e628b2d9 authored by Hans Muller's avatar Hans Muller

Merge pull request #1596 from HansMuller/scrolling_demos

Added a flexible appbar gallery demo

Added a "Patterns/Scrolling Techniques" demo that resembles the "Flexible Space with Image" from the Material design spec - https://www.google.com/design/spec/patterns/scrolling-techniques.html#scrolling-techniques-scrolling

Demos for the other app bar arrangements are still needed.
parents aa6c761a 8741f33e
name: material_gallery
assets:
- assets/ali_connors.png
- assets/flutter_logo.png
- assets/section_animation.png
- assets/section_style.png
......@@ -25,11 +26,17 @@ material-design-icons:
- name: navigation/expand_less
- name: navigation/expand_more
- name: navigation/menu
- name: navigation/more_horiz
- name: navigation/more_vert
- name: action/event
- name: action/home
- name: action/android
- name: action/alarm
- name: action/face
- name: action/language
- name: communication/call
- name: communication/email
- name: communication/location_on
- name: communication/message
- name: content/add
- name: content/create
// 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/widgets.dart';
class _ContactCategory extends StatelessComponent {
_ContactCategory({ Key key, this.icon, this.children }) : super(key: key);
final String icon;
final List<Widget> children;
Widget build(BuildContext context) {
return new Container(
padding: const EdgeDims.symmetric(vertical: 16.0),
decoration: new BoxDecoration(
border: new Border(bottom: new BorderSide(color: Theme.of(context).dividerColor))
),
child: new DefaultTextStyle(
style: Theme.of(context).text.subhead,
child: new Row(
children: <Widget>[
new SizedBox(
width: 72.0,
child: new Icon(icon: icon, color: Theme.of(context).primaryColor)
),
new Flexible(child: new Column(children: children))
]
)
)
);
}
}
class _ContactItem extends StatelessComponent {
_ContactItem({ Key key, this.icon, this.lines }) : super(key: key) {
assert(lines.length > 1);
}
final String icon;
final List<String> lines;
Widget build(BuildContext context) {
List<Widget> columnChildren = lines.sublist(0, lines.length - 1).map((String line) => new Text(line)).toList();
columnChildren.add(new Text(lines.last, style: Theme.of(context).text.caption));
List<Widget> rowChildren = <Widget>[
new Column(
alignItems: FlexAlignItems.start,
children: columnChildren
)
];
if (icon != null) {
rowChildren.add(new SizedBox(
width: 72.0,
child: new Icon(icon: icon, color: Theme.of(context).disabledColor)
));
}
return new Padding(
padding: const EdgeDims.symmetric(vertical: 16.0),
child: new Row(
justifyContent: FlexJustifyContent.spaceBetween,
children: rowChildren
)
);
}
}
class FlexibleSpaceDemo extends StatefulComponent {
FlexibleSpaceDemoState createState() => new FlexibleSpaceDemoState();
}
class FlexibleSpaceDemoState extends State<FlexibleSpaceDemo> {
final double appBarHeight = 256.0;
final Key scrollableKey = new UniqueKey();
Widget build(BuildContext context) {
return new Theme(
data: new ThemeData(
brightness: ThemeBrightness.light,
primarySwatch: Colors.indigo
),
child: new Scaffold(
appBarHeight: appBarHeight,
scrollableKey: scrollableKey,
appBarBehavior: AppBarBehavior.scroll,
toolBar: new ToolBar(
right: <Widget>[
new IconButton(
icon: 'content/create',
tooltip: 'Search'
),
new IconButton(
icon: 'navigation/more_vert',
tooltip: 'Show menu'
)
],
flexibleSpace: (BuildContext context) {
return new FlexibleSpaceBar(
title : new Text('Ali Connors'),
image: new AssetImage(
name: 'assets/ali_connors.png',
fit: ImageFit.cover,
height: appBarHeight
)
);
}
),
body: new Block(
scrollableKey: scrollableKey,
padding: new EdgeDims.only(top: appBarHeight),
children: <Widget>[
new _ContactCategory(
icon: 'communication/call',
children: <Widget>[
new _ContactItem(
icon: 'communication/message',
lines: <String>[
'(650) 555-1234',
'Mobile'
]
),
new _ContactItem(
icon: 'communication/message',
lines: <String>[
'(323) 555-6789',
'Work'
]
)
]
),
new _ContactCategory(
icon: 'communication/email',
children: <Widget>[
new _ContactItem(
lines: <String>[
'ali_connors@example.com',
'Personal'
]
),
new _ContactItem(
lines: <String>[
'aliconnors@example.com',
'Work'
]
)
]
),
new _ContactCategory(
icon: 'communication/location_on',
children: <Widget>[
new _ContactItem(
lines: <String>[
'2000 Main Street',
'San Francisco, CA',
'Home'
]
),
new _ContactItem(
lines: <String>[
'1600 Amphitheater Parkway',
'Mountain View, CA',
'Work'
]
),
new _ContactItem(
lines: <String>[
'126 Severyns Ave',
'Mountain View, CA',
'Jet Travel'
]
)
]
)
]
)
)
);
}
}
// 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 'flexible_space_demo.dart';
class _BarGraphic extends StatelessComponent {
_BarGraphic({ Key key, this.height, this.color, this.leftText, this.rightText: '' })
: super(key: key) {
assert(height != null);
assert(color != null);
assert(leftText != null);
}
final double height;
final Color color;
final String leftText;
final String rightText;
Widget build(BuildContext context) {
return new Container(
height: height,
width: 200.0,
padding: const EdgeDims.symmetric(horizontal: 16.0),
decoration: new BoxDecoration(backgroundColor: color),
child: new DefaultTextStyle(
style: Theme.of(context).text.body1.copyWith(color: Colors.white),
child: new Row(
justifyContent: FlexJustifyContent.spaceBetween,
children: <Widget>[
new Text(leftText),
new Text(rightText)
]
)
)
);
}
}
class _StatusBarGraphic extends _BarGraphic {
_StatusBarGraphic() : super(
height: 24.0,
color: Colors.green[400],
leftText: 'Status Bar',
rightText: '24dp'
);
}
class _ToolBarGraphic extends _BarGraphic {
_ToolBarGraphic() : super(
height: 48.0,
color: Colors.blue[400],
leftText: 'Tool Bar',
rightText: '48dp'
);
}
class _TabBarGraphic extends _BarGraphic {
_TabBarGraphic() : super(
height: 48.0,
color: Colors.purple[400],
leftText: 'Tab Bar',
rightText: '56dp'
);
}
class _FlexibleSpaceGraphic extends _BarGraphic {
_FlexibleSpaceGraphic() : super(
height: 128.0,
color: Colors.pink[400],
leftText: 'Flexible Space'
);
}
class _TechniqueItem extends StatelessComponent {
_TechniqueItem({ this.titleText, this.barGraphics, this.builder });
final String titleText;
final List<Widget> barGraphics;
final WidgetBuilder builder;
void showDemo(BuildContext context) {
Navigator.push(context, new MaterialPageRoute(builder: builder));
}
Widget build(BuildContext context) {
return new Card(
child: new InkWell(
onTap: () { showDemo(context); },
child: new Padding(
padding: const EdgeDims.all(16.0),
child: new Row(
justifyContent: FlexJustifyContent.spaceBetween,
children :<Widget>[
new Text(titleText),
new Column(children: barGraphics)
]
)
)
)
);
}
}
const String _introText =
"An AppBar is a combination of a ToolBar and a TabBar or a flexible space "
"Widget that is managed by the Scaffold. The Scaffold pads the ToolBar so that "
"it appears behind the device's status bar. When a flexible space Widget is "
"specified it is stacked on top of the ToolBar.";
class ScrollingTechniquesDemo extends StatelessComponent {
Widget build(BuildContext context) {
return new Scaffold(
toolBar: new ToolBar(center: new Text('Scrolling Techniques')),
body: new Padding(
padding: const EdgeDims.symmetric(horizontal: 16.0),
child: new Block(
children: <Widget>[
new Padding(
padding: const EdgeDims.symmetric(horizontal: 16.0, vertical: 32.0),
child: new Text(_introText, style: Theme.of(context).text.caption)
),
new _TechniqueItem(
builder: (BuildContext context) => new FlexibleSpaceDemo(),
titleText: 'Standard',
barGraphics: <Widget>[
new _StatusBarGraphic(),
new _ToolBarGraphic()
]
),
new _TechniqueItem(
titleText: 'Tabs',
builder: (BuildContext context) => new FlexibleSpaceDemo(),
barGraphics: <Widget>[
new _StatusBarGraphic(),
new _ToolBarGraphic(),
new _TabBarGraphic()
]
),
new _TechniqueItem(
titleText: 'Flexible',
builder: (BuildContext context) => new FlexibleSpaceDemo(),
barGraphics: <Widget>[
new _StatusBarGraphic(),
new _ToolBarGraphic(),
new _FlexibleSpaceGraphic()
]
)
]
)
)
);
}
}
......@@ -12,17 +12,20 @@ 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/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 WidgetBuilder builder;
final GalleryDemoBuilder builder;
}
class GallerySection extends StatelessComponent {
......@@ -36,7 +39,7 @@ class GallerySection extends StatelessComponent {
void showDemo(GalleryDemo demo, BuildContext context, ThemeData theme) {
Navigator.push(context, new MaterialPageRoute(
builder: (BuildContext context) {
Widget child = (demo.builder == null) ? null : demo.builder(context);
Widget child = (demo.builder == null) ? null : demo.builder();
return new Theme(data: theme, child: child);
}
));
......@@ -150,7 +153,7 @@ class GalleryHome extends StatelessComponent {
image: 'assets/section_animation.png',
colors: Colors.purple,
demos: <GalleryDemo>[
new GalleryDemo(title: 'Weathers', builder: (BuildContext context) => new WeathersDemo())
new GalleryDemo(title: 'Weathers', builder: () => new WeathersDemo())
]
),
new GallerySection(
......@@ -172,18 +175,18 @@ class GalleryHome extends StatelessComponent {
image: 'assets/section_components.png',
colors: Colors.amber,
demos: <GalleryDemo>[
new GalleryDemo(title: 'Modal Bottom Sheet', builder: (_) => new ModalBottomSheetDemo()),
new GalleryDemo(title: 'Persistent Bottom Sheet', builder: (_) => new PersistentBottomSheetDemo()),
new GalleryDemo(title: 'Chips', builder: (_) => new ChipDemo()),
new GalleryDemo(title: 'Progress Indicators', builder: (_) => new ProgressIndicatorDemo()),
new GalleryDemo(title: 'Sliders', builder: (_) => new SliderDemo()),
new GalleryDemo(title: 'Selection Controls', builder: (_) => new ToggleControlsDemo()),
new GalleryDemo(title: 'Dropdown Button', builder: (_) => new DropDownDemo()),
new GalleryDemo(title: 'Tabs', builder: (_) => new TabsDemo()),
new GalleryDemo(title: 'Expland/Collapse List Control', builder: (_) => new TwoLevelListDemo()),
new GalleryDemo(title: 'Page Selector', builder: (_) => new PageSelectorDemo()),
new GalleryDemo(title: 'Date Picker', builder: (_) => new DatePickerDemo()),
new GalleryDemo(title: 'Time Picker', builder: (_) => new TimePickerDemo())
new GalleryDemo(title: 'Modal Bottom Sheet', builder: () => new ModalBottomSheetDemo()),
new GalleryDemo(title: 'Persistent Bottom Sheet', builder: () => new PersistentBottomSheetDemo()),
new GalleryDemo(title: 'Chips', builder: () => new ChipDemo()),
new GalleryDemo(title: 'Progress Indicators', builder: () => new ProgressIndicatorDemo()),
new GalleryDemo(title: 'Sliders', builder: () => new SliderDemo()),
new GalleryDemo(title: 'Selection Controls', builder: () => new ToggleControlsDemo()),
new GalleryDemo(title: 'Dropdown Button', builder: () => new DropDownDemo()),
new GalleryDemo(title: 'Tabs', builder: () => new TabsDemo()),
new GalleryDemo(title: 'Expland/Collapse List Control', builder: () => new TwoLevelListDemo()),
new GalleryDemo(title: 'Page Selector', builder: () => new PageSelectorDemo()),
new GalleryDemo(title: 'Date Picker', builder: () => new DatePickerDemo()),
new GalleryDemo(title: 'Time Picker', builder: () => new TimePickerDemo())
]
)
]
......@@ -193,7 +196,10 @@ class GalleryHome extends StatelessComponent {
new GallerySection(
title: 'Patterns',
image: 'assets/section_patterns.png',
colors: Colors.cyan
colors: Colors.cyan,
demos: <GalleryDemo>[
new GalleryDemo(title: 'Scrolling Techniques', builder: () => new ScrollingTechniquesDemo())
]
),
new GallerySection(
title: 'Usability',
......
......@@ -446,7 +446,8 @@ class Block extends StatelessComponent {
this.padding,
this.initialScrollOffset,
this.scrollDirection: Axis.vertical,
this.onScroll
this.onScroll,
this.scrollableKey
}) : super(key: key) {
assert(!children.any((Widget child) => child == null));
}
......@@ -456,12 +457,14 @@ class Block extends StatelessComponent {
final double initialScrollOffset;
final Axis scrollDirection;
final ScrollListener onScroll;
final Key scrollableKey;
Widget build(BuildContext context) {
Widget contents = new BlockBody(children: children, direction: scrollDirection);
if (padding != null)
contents = new Padding(padding: padding, child: contents);
return new ScrollableViewport(
key: scrollableKey,
initialScrollOffset: initialScrollOffset,
scrollDirection: scrollDirection,
onScroll: onScroll,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment