Unverified Commit 3a2e0d93 authored by Hans Muller's avatar Hans Muller Committed by GitHub

Extended ButtonTheme, RoundedRectangleBorder, gallery buttons demo (#15723)

parent 05ccf56c
...@@ -53,25 +53,40 @@ class ButtonsDemo extends StatefulWidget { ...@@ -53,25 +53,40 @@ class ButtonsDemo extends StatefulWidget {
} }
class _ButtonsDemoState extends State<ButtonsDemo> { class _ButtonsDemoState extends State<ButtonsDemo> {
ShapeBorder _buttonShape;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final ButtonThemeData buttonTheme = ButtonTheme.of(context).copyWith(
shape: _buttonShape
);
final List<ComponentDemoTabData> demos = <ComponentDemoTabData>[ final List<ComponentDemoTabData> demos = <ComponentDemoTabData>[
new ComponentDemoTabData( new ComponentDemoTabData(
tabName: 'RAISED', tabName: 'RAISED',
description: _raisedText, description: _raisedText,
demoWidget: buildRaisedButton(), demoWidget: new ButtonTheme.fromButtonThemeData(
data: buttonTheme,
child: buildRaisedButton(),
),
exampleCodeTag: _raisedCode, exampleCodeTag: _raisedCode,
), ),
new ComponentDemoTabData( new ComponentDemoTabData(
tabName: 'FLAT', tabName: 'FLAT',
description: _flatText, description: _flatText,
demoWidget: buildFlatButton(), demoWidget: new ButtonTheme.fromButtonThemeData(
data: buttonTheme,
child: buildFlatButton(),
),
exampleCodeTag: _flatCode, exampleCodeTag: _flatCode,
), ),
new ComponentDemoTabData( new ComponentDemoTabData(
tabName: 'OUTLINE', tabName: 'OUTLINE',
description: _outlineText, description: _outlineText,
demoWidget: buildOutlineButton(), demoWidget: new ButtonTheme.fromButtonThemeData(
data: buttonTheme,
child: buildOutlineButton(),
),
exampleCodeTag: _outlineCode, exampleCodeTag: _outlineCode,
), ),
new ComponentDemoTabData( new ComponentDemoTabData(
...@@ -97,6 +112,16 @@ class _ButtonsDemoState extends State<ButtonsDemo> { ...@@ -97,6 +112,16 @@ class _ButtonsDemoState extends State<ButtonsDemo> {
return new TabbedComponentDemoScaffold( return new TabbedComponentDemoScaffold(
title: 'Buttons', title: 'Buttons',
demos: demos, demos: demos,
actions: <Widget>[
new IconButton(
icon: const Icon(Icons.sentiment_very_satisfied),
onPressed: () {
setState(() {
_buttonShape = _buttonShape == null ? const StadiumBorder() : null;
});
},
),
],
); );
} }
......
...@@ -63,9 +63,9 @@ class ScrollableTabsDemoState extends State<ScrollableTabsDemo> with SingleTicke ...@@ -63,9 +63,9 @@ class ScrollableTabsDemoState extends State<ScrollableTabsDemo> with SingleTicke
}); });
} }
ShapeDecoration getIndicator() { Decoration getIndicator() {
if (!_customIndicator) if (!_customIndicator)
return null; return const UnderlineTabIndicator();
switch(_demoStyle) { switch(_demoStyle) {
case TabsDemoStyle.iconsAndText: case TabsDemoStyle.iconsAndText:
......
...@@ -35,11 +35,13 @@ class ComponentDemoTabData { ...@@ -35,11 +35,13 @@ class ComponentDemoTabData {
class TabbedComponentDemoScaffold extends StatelessWidget { class TabbedComponentDemoScaffold extends StatelessWidget {
const TabbedComponentDemoScaffold({ const TabbedComponentDemoScaffold({
this.title, this.title,
this.demos this.demos,
this.actions,
}); });
final List<ComponentDemoTabData> demos; final List<ComponentDemoTabData> demos;
final String title; final String title;
final List<Widget> actions;
void _showExampleCode(BuildContext context) { void _showExampleCode(BuildContext context) {
final String tag = demos[DefaultTabController.of(context).index].exampleCodeTag; final String tag = demos[DefaultTabController.of(context).index].exampleCodeTag;
...@@ -57,19 +59,21 @@ class TabbedComponentDemoScaffold extends StatelessWidget { ...@@ -57,19 +59,21 @@ class TabbedComponentDemoScaffold extends StatelessWidget {
child: new Scaffold( child: new Scaffold(
appBar: new AppBar( appBar: new AppBar(
title: new Text(title), title: new Text(title),
actions: <Widget>[ actions: (actions ?? <Widget>[])..addAll(
new Builder( <Widget>[
builder: (BuildContext context) { new Builder(
return new IconButton( builder: (BuildContext context) {
icon: const Icon(Icons.description), return new IconButton(
tooltip: 'Show example code', icon: const Icon(Icons.description),
onPressed: () { tooltip: 'Show example code',
_showExampleCode(context); onPressed: () {
}, _showExampleCode(context);
); },
}, );
), },
], )
],
),
bottom: new TabBar( bottom: new TabBar(
isScrollable: true, isScrollable: true,
tabs: demos.map((ComponentDemoTabData data) => new Tab(text: data.tabName)).toList(), tabs: demos.map((ComponentDemoTabData data) => new Tab(text: data.tabName)).toList(),
......
...@@ -80,6 +80,16 @@ class ButtonTheme extends InheritedWidget { ...@@ -80,6 +80,16 @@ class ButtonTheme extends InheritedWidget {
), ),
super(key: key, child: child); super(key: key, child: child);
/// Creates a button theme from [data].
///
/// The [data] argument must not be null.
const ButtonTheme.fromButtonThemeData({
Key key,
@required this.data,
Widget child,
}) : assert(data != null),
super(key: key, child: child);
/// Creates a button theme that is appropriate for button bars, as used in /// Creates a button theme that is appropriate for button bars, as used in
/// dialog footers and in the headers of data tables. /// dialog footers and in the headers of data tables.
/// ///
...@@ -248,6 +258,26 @@ class ButtonThemeData extends Diagnosticable { ...@@ -248,6 +258,26 @@ class ButtonThemeData extends Diagnosticable {
/// This property only affects [DropdownButton] and its menu. /// This property only affects [DropdownButton] and its menu.
final bool alignedDropdown; final bool alignedDropdown;
/// Creates a copy of this button theme data object with the matching fields
/// replaced with the non-null parameter values.
ButtonThemeData copyWith({
ButtonTextTheme textTheme,
double minWidth,
double height,
EdgeInsetsGeometry padding,
ShapeBorder shape,
bool alignedDropdown,
}) {
return new ButtonThemeData(
textTheme: textTheme ?? this.textTheme,
minWidth: minWidth ?? this.minWidth,
height: height ?? this.height,
padding: padding ?? this.padding,
shape: shape ?? this.shape,
alignedDropdown: alignedDropdown ?? this.alignedDropdown,
);
}
@override @override
bool operator ==(dynamic other) { bool operator ==(dynamic other) {
if (other.runtimeType != runtimeType) if (other.runtimeType != runtimeType)
......
...@@ -454,7 +454,7 @@ class _OutlineBorder extends ShapeBorder { ...@@ -454,7 +454,7 @@ class _OutlineBorder extends ShapeBorder {
if (a is _OutlineBorder) { if (a is _OutlineBorder) {
return new _OutlineBorder( return new _OutlineBorder(
side: BorderSide.lerp(a.side, side, t), side: BorderSide.lerp(a.side, side, t),
shape: shape.lerpFrom(a.shape, t), shape: ShapeBorder.lerp(a.shape, shape, t),
); );
} }
return super.lerpFrom(a, t); return super.lerpFrom(a, t);
...@@ -466,7 +466,7 @@ class _OutlineBorder extends ShapeBorder { ...@@ -466,7 +466,7 @@ class _OutlineBorder extends ShapeBorder {
if (b is _OutlineBorder) { if (b is _OutlineBorder) {
return new _OutlineBorder( return new _OutlineBorder(
side: BorderSide.lerp(side, b.side, t), side: BorderSide.lerp(side, b.side, t),
shape: shape.lerpTo(b.shape, t), shape: ShapeBorder.lerp(shape, b.shape, t),
); );
} }
return super.lerpTo(b, t); return super.lerpTo(b, t);
......
...@@ -74,6 +74,31 @@ void main() { ...@@ -74,6 +74,31 @@ void main() {
expect(tester.getSize(find.byType(Material)), const Size(88.0, 36.0)); expect(tester.getSize(find.byType(Material)), const Size(88.0, 36.0));
}); });
test('ButtonThemeData.copyWith', () {
ButtonThemeData theme = const ButtonThemeData().copyWith();
expect(theme.textTheme, ButtonTextTheme.normal);
expect(theme.constraints, const BoxConstraints(minWidth: 88.0, minHeight: 36.0));
expect(theme.padding, const EdgeInsets.symmetric(horizontal: 16.0));
expect(theme.shape, const RoundedRectangleBorder(
borderRadius: const BorderRadius.all(const Radius.circular(2.0)),
));
expect(theme.alignedDropdown, false);
theme = const ButtonThemeData().copyWith(
textTheme: ButtonTextTheme.primary,
minWidth: 100.0,
height: 200.0,
padding: EdgeInsets.zero,
shape: const StadiumBorder(),
alignedDropdown: true,
);
expect(theme.textTheme, ButtonTextTheme.primary);
expect(theme.constraints, const BoxConstraints(minWidth: 100.0, minHeight: 200.0));
expect(theme.padding, EdgeInsets.zero);
expect(theme.shape, const StadiumBorder());
expect(theme.alignedDropdown, true);
});
testWidgets('Theme buttonTheme defaults', (WidgetTester tester) async { testWidgets('Theme buttonTheme defaults', (WidgetTester tester) async {
final ThemeData lightTheme = new ThemeData.light(); final ThemeData lightTheme = new ThemeData.light();
ButtonTextTheme textTheme; ButtonTextTheme textTheme;
......
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