Last active
July 14, 2022 23:51
Revisions
-
contactjavas revised this gist
Jul 14, 2022 . 1 changed file with 1 addition and 5 deletions.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,8 +1,4 @@ import 'package:flutter/material.dart'; /// begin_library_part /// -
contactjavas revised this gist
Jul 12, 2022 . No changes.There are no files selected for viewing
-
contactjavas revised this gist
Jul 12, 2022 . 1 changed file with 280 additions and 0 deletions.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -305,3 +305,283 @@ class _EasyButtonState extends State<EasyButton> with TickerProviderStateMixin { _animController!.reverse(); } } /// end_library_part /// begin_example_part void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( title: 'Easy Loading Button', debugShowCheckedModeBanner: false, theme: ThemeData( primarySwatch: Colors.blue, ), home: const ExamplePage(title: 'Easy Loading Button'), ); } } class ExamplePage extends StatefulWidget { const ExamplePage({Key? key, required this.title}) : super(key: key); final String title; @override State<ExamplePage> createState() => _ExamplePageState(); } class _ExamplePageState extends State<ExamplePage> { @override Widget build(BuildContext context) { onButtonPressed() async { await Future.delayed(const Duration(milliseconds: 3000), () => 42); // After [onPressed], it will trigger animation running backwards, from end to beginning return () { // Optional returns is returning a VoidCallback that will be called // after the animation is stopped at the beginning. // A best practice would be to do time-consuming task in [onPressed], // and do page navigation in the returned VoidCallback. // So that user won't missed out the reverse animation. }; } return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ const SizedBox( height: 15, ), const Text( 'Elevated button', ), const SizedBox( height: 5, ), EasyButton( idleStateWidget: const Text( 'Elevated button', style: TextStyle( color: Colors.white, ), ), loadingStateWidget: const CircularProgressIndicator( strokeWidth: 3.0, valueColor: AlwaysStoppedAnimation<Color>( Colors.white, ), ), useEqualLoadingStateWidgetDimension: true, useWidthAnimation: false, width: 150.0, height: 40.0, borderRadius: 4.0, elevation: 2.0, contentGap: 6.0, buttonColor: Colors.blueAccent, onPressed: onButtonPressed, ), const SizedBox( height: 15, ), const Text( 'Elevated button (width animated)', ), const SizedBox( height: 5, ), EasyButton( idleStateWidget: const Text( 'Elevated button', style: TextStyle( color: Colors.white, ), ), loadingStateWidget: const CircularProgressIndicator( strokeWidth: 3.0, valueColor: AlwaysStoppedAnimation<Color>( Colors.white, ), ), useWidthAnimation: true, useEqualLoadingStateWidgetDimension: true, width: 150.0, height: 40.0, borderRadius: 4.0, contentGap: 6.0, buttonColor: Colors.blueAccent, onPressed: onButtonPressed, ), const SizedBox( height: 15, ), const Text( 'Outlined button', ), const SizedBox( height: 5, ), EasyButton( type: EasyButtonType.outlined, idleStateWidget: const Text( 'Outlined button', style: TextStyle( color: Colors.blueAccent, ), ), loadingStateWidget: const CircularProgressIndicator( strokeWidth: 3.0, valueColor: AlwaysStoppedAnimation<Color>( Colors.blueAccent, ), ), useEqualLoadingStateWidgetDimension: true, useWidthAnimation: false, width: 150.0, height: 40.0, borderRadius: 4.0, contentGap: 6.0, onPressed: onButtonPressed, ), const SizedBox( height: 15, ), const Text( 'Outlined button (width animated)', ), const SizedBox( height: 5, ), EasyButton( type: EasyButtonType.outlined, idleStateWidget: const Text( 'Outlined button', style: TextStyle( color: Colors.blueAccent, ), ), loadingStateWidget: const CircularProgressIndicator( strokeWidth: 3.0, valueColor: AlwaysStoppedAnimation<Color>( Colors.blueAccent, ), ), useWidthAnimation: true, useEqualLoadingStateWidgetDimension: true, width: 150.0, height: 40.0, borderRadius: 4.0, contentGap: 6.0, onPressed: onButtonPressed, ), const SizedBox( height: 15, ), const Text( 'Text button', ), const SizedBox( height: 5, ), EasyButton( type: EasyButtonType.text, idleStateWidget: const Text( 'Text button', style: TextStyle( color: Colors.blueAccent, ), ), loadingStateWidget: const CircularProgressIndicator( strokeWidth: 3.0, valueColor: AlwaysStoppedAnimation<Color>( Colors.blueAccent, ), ), useEqualLoadingStateWidgetDimension: true, useWidthAnimation: false, width: 150.0, height: 28.0, borderRadius: 4.0, onPressed: onButtonPressed, ), const SizedBox( height: 15, ), const Text( 'Fullwidth elevated button', ), const SizedBox( height: 5, ), EasyButton( idleStateWidget: const Text( 'Fullwidth elevated button', style: TextStyle( color: Colors.white, ), ), loadingStateWidget: const CircularProgressIndicator( strokeWidth: 3.0, valueColor: AlwaysStoppedAnimation<Color>( Colors.white, ), ), useEqualLoadingStateWidgetDimension: true, useWidthAnimation: false, width: double.infinity, height: 40.0, contentGap: 6.0, buttonColor: Colors.blueAccent, onPressed: onButtonPressed, ), const SizedBox( height: 15, ), const Text( 'Fullwidth elevated button (width animated)', ), const SizedBox( height: 5, ), EasyButton( idleStateWidget: const Text( 'Fullwidth elevated button', style: TextStyle( color: Colors.white, ), ), loadingStateWidget: const CircularProgressIndicator( strokeWidth: 3.0, valueColor: AlwaysStoppedAnimation<Color>( Colors.white, ), ), useWidthAnimation: true, useEqualLoadingStateWidgetDimension: true, width: double.infinity, height: 40.0, contentGap: 6.0, buttonColor: Colors.blueAccent, onPressed: onButtonPressed, ), ], ), ), // This trailing comma makes auto-formatting nicer for build methods. ); } } -
contactjavas revised this gist
Jul 12, 2022 . 1 changed file with 12 additions and 0 deletions.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,3 +1,15 @@ /// Note: /// In the DartPad version, our use of `CircularProgressIndicator` as the `loadingStateWidget` is not well-displayed. /// But it's fine when using it in mobile phone (Android, in our test). import 'package:flutter/material.dart'; /// begin_library_part /// /// When writing this example, DartPad didn't support (many/almost all) custom packages /// If you want to directly check for the related code (not the library), /// then please search (in this DartPad) for this keyword: begin_example_part enum EasyButtonState { idle, loading, -
contactjavas revised this gist
Jul 12, 2022 . 1 changed file with 11 additions and 302 deletions.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,15 +1,3 @@ enum EasyButtonState { idle, loading, @@ -31,16 +19,16 @@ class EasyButton extends StatefulWidget { /// The button type. final EasyButtonType type; /// Whether or not to animate the width of the button. Default is `true`. /// /// If this is set to `false`, you might want to set the `useEqualLoadingStateWidgetDimension` parameter to `true`. final bool useWidthAnimation; /// Whether or not to force the `loadingStateWidget` to have equal dimension. /// /// This is useful when you are using `CircularProgressIndicator` as the `loadingStateWidget`. /// /// This parameter might also be useful when you set the `useWidthAnimation` parameter to `true` combined with `CircularProgressIndicator` as the value for `loadingStateWidget`. final bool useEqualLoadingStateWidgetDimension; /// The button width. @@ -91,7 +79,7 @@ class EasyButton extends StatefulWidget { }) : super(key: key); @override State createState() => _EasyButtonState(); } class _EasyButtonState extends State<EasyButton> with TickerProviderStateMixin { @@ -181,20 +169,20 @@ class _EasyButtonState extends State<EasyButton> with TickerProviderStateMixin { case EasyButtonType.elevated: return ElevatedButton( style: elevatedButtonStyle, onPressed: _onButtonPressed(), child: _buildChildren(context), ); case EasyButtonType.outlined: return TextButton( style: outlinedButtonStyle, onPressed: _onButtonPressed(), child: _buildChildren(context), ); case EasyButtonType.text: return TextButton( style: textButtonStyle, onPressed: _onButtonPressed(), child: _buildChildren(context), ); } } @@ -210,14 +198,13 @@ class _EasyButtonState extends State<EasyButton> with TickerProviderStateMixin { break; case EasyButtonState.loading: contentWidget = widget.loadingStateWidget; if (widget.useEqualLoadingStateWidgetDimension) { contentWidget = SizedBox.square( dimension: widget.height - (contentGap * 2), child: widget.loadingStateWidget, ); } break; @@ -306,281 +293,3 @@ class _EasyButtonState extends State<EasyButton> with TickerProviderStateMixin { _animController!.reverse(); } } -
contactjavas revised this gist
Apr 16, 2022 . 1 changed file with 17 additions and 5 deletions.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -28,6 +28,7 @@ class EasyButton extends StatefulWidget { /// Content inside the button when the button state is loading. final Widget loadingStateWidget; /// The button type. final EasyButtonType type; /// Whether or not to animate the width of the button. @@ -41,13 +42,19 @@ class EasyButton extends StatefulWidget { /// /// This parameter will be ignored when `useWidthAnimation` value is `true`. final bool useEqualLoadingStateWidgetDimension; /// The button width. final double width; /// The button height. final double height; /// The gap between button and it's content. /// /// This will be ignored when the `type` parameter value is set to `EasyButtonType.text` final double contentGap; /// The visual border radius of the button. final double borderRadius; /// The elevation of the button. @@ -63,6 +70,8 @@ class EasyButton extends StatefulWidget { /// /// For [`EasyButtonType.text`]: This will be the text color. final Color buttonColor; /// Function to run when button is pressed. final Function? onPressed; const EasyButton({ @@ -89,7 +98,7 @@ class _EasyButtonState extends State<EasyButton> with TickerProviderStateMixin { final GlobalKey _globalKey = GlobalKey(); Animation? _anim; AnimationController? _animController; final Duration _duration = const Duration( milliseconds: 250, ); @@ -100,7 +109,10 @@ class _EasyButtonState extends State<EasyButton> with TickerProviderStateMixin { @override dispose() { if (_animController != null) { _animController!.dispose(); } super.dispose(); } @@ -277,7 +289,7 @@ class _EasyButtonState extends State<EasyButton> with TickerProviderStateMixin { double targetBorderRadius = _height / 2; _animController = AnimationController(duration: _duration, vsync: this); _anim = Tween(begin: 0.0, end: 1.0).animate(_animController!) ..addListener(() { setState(() { _width = initialWidth - ((initialWidth - targetWidth) * _anim!.value); @@ -287,11 +299,11 @@ class _EasyButtonState extends State<EasyButton> with TickerProviderStateMixin { }) ..addStatusListener(stateListener); _animController!.forward(); } void _reverse() { _animController!.reverse(); } } -
contactjavas revised this gist
Apr 11, 2022 . 1 changed file with 4 additions and 0 deletions.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,3 +1,7 @@ /// Note: /// In the DartPad version, our use of `CircularProgressIndicator` as the `loadingStateWidget` is not well-displayed. /// But it's fine when using it in mobile phone (Android, in our test). import 'package:flutter/material.dart'; /// begin_library_part -
contactjavas created this gist
Apr 11, 2022 .There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,570 @@ import 'package:flutter/material.dart'; /// begin_library_part /// /// When writing this example, DartPad didn't support (many/almost all) custom packages /// If you want to directly check for the related code (not the library), /// then please search (in this DartPad) for this keyword: begin_example_part enum EasyButtonState { idle, loading, } enum EasyButtonType { elevated, outlined, text, } class EasyButton extends StatefulWidget { /// Content inside the button when the button state is idle. final Widget idleStateWidget; /// Content inside the button when the button state is loading. final Widget loadingStateWidget; final EasyButtonType type; /// Whether or not to animate the width of the button. /// /// If this is set to `false`, you might want to also check the `useEqualLoadingStateWidgetDimension` parameter and set it to `true`. final bool useWidthAnimation; /// Whether or not to force the `loadingStateWidget` to have equal dimension when `useWidthAnimation` is set to false. /// /// This is useful when you are using `CircularProgressIndicator` as the `loadingStateWidget`. /// /// This parameter will be ignored when `useWidthAnimation` value is `true`. final bool useEqualLoadingStateWidgetDimension; final double width; final double height; /// The gap between button and it's content. /// /// This will be ignored when the `type` parameter value is set to `EasyButtonType.text` final double contentGap; final double borderRadius; /// The elevation of the button. /// /// This will only be applied when the `type` parameter value is `EasyButtonType.elevated` final double elevation; /// Color for the button. /// /// For [`EasyButtonType.elevated`]: This will be the background color. /// /// For [`EasyButtonType.outlined`]: This will be the border color. /// /// For [`EasyButtonType.text`]: This will be the text color. final Color buttonColor; final Function? onPressed; const EasyButton({ Key? key, required this.idleStateWidget, required this.loadingStateWidget, this.type = EasyButtonType.elevated, this.useWidthAnimation = true, this.useEqualLoadingStateWidgetDimension = true, this.width = double.infinity, this.height = 40.0, this.contentGap = 0.0, this.borderRadius = 0.0, this.elevation = 0.0, this.buttonColor = Colors.blueAccent, this.onPressed, }) : super(key: key); @override _EasyButtonState createState() => _EasyButtonState(); } class _EasyButtonState extends State<EasyButton> with TickerProviderStateMixin { final GlobalKey _globalKey = GlobalKey(); Animation? _anim; late AnimationController _animController; final Duration _duration = const Duration( milliseconds: 250, ); EasyButtonState _state = EasyButtonState.idle; late double _width; late double _height; late double _borderRadius; @override dispose() { _animController.dispose(); super.dispose(); } @override void deactivate() { _reset(); super.deactivate(); } @override void initState() { _reset(); super.initState(); } void _reset() { _state = EasyButtonState.idle; _width = widget.width; _height = widget.height; _borderRadius = widget.borderRadius; } @override Widget build(BuildContext context) { return PhysicalModel( color: Colors.transparent, borderRadius: BorderRadius.circular(_borderRadius), child: SizedBox( key: _globalKey, height: _height, width: _width, child: _buildChild(context), ), ); } Widget _buildChild(BuildContext context) { var padding = EdgeInsets.all( widget.contentGap, ); var buttonColor = widget.buttonColor; var shape = RoundedRectangleBorder( borderRadius: BorderRadius.circular(_borderRadius), ); final ButtonStyle elevatedButtonStyle = ElevatedButton.styleFrom( padding: padding, primary: buttonColor, elevation: widget.elevation, shape: shape, ); final ButtonStyle outlinedButtonStyle = OutlinedButton.styleFrom( padding: padding, shape: shape, side: BorderSide( color: buttonColor, ), ); final ButtonStyle textButtonStyle = TextButton.styleFrom( padding: padding, ); switch (widget.type) { case EasyButtonType.elevated: return ElevatedButton( style: elevatedButtonStyle, child: _buildChildren(context), onPressed: _onButtonPressed(), ); case EasyButtonType.outlined: return TextButton( style: outlinedButtonStyle, child: _buildChildren(context), onPressed: _onButtonPressed(), ); case EasyButtonType.text: return TextButton( style: textButtonStyle, child: _buildChildren(context), onPressed: _onButtonPressed(), ); } } Widget _buildChildren(BuildContext context) { double contentGap = widget.type == EasyButtonType.text ? 0.0 : widget.contentGap; Widget contentWidget; switch (_state) { case EasyButtonState.idle: contentWidget = widget.idleStateWidget; break; case EasyButtonState.loading: if (!widget.useWidthAnimation && widget.useEqualLoadingStateWidgetDimension) { contentWidget = SizedBox.square( dimension: widget.height - (contentGap * 2), child: widget.loadingStateWidget, ); } else { contentWidget = widget.loadingStateWidget; } break; } return contentWidget; } VoidCallback _onButtonPressed() { if (widget.onPressed == null) { return () {}; } return _manageLoadingState; } Future _manageLoadingState() async { if (_state != EasyButtonState.idle) { return; } // The result of widget.onPressed() will be called as VoidCallback after button status is back to default. dynamic onIdle; if (widget.useWidthAnimation) { _toProcessing(); _forward((status) { if (status == AnimationStatus.dismissed) { _toDefault(); if (onIdle != null && (onIdle is VoidCallback || onIdle is FormFieldValidator)) { onIdle(); } } }); onIdle = await widget.onPressed!(); _reverse(); } else { _toProcessing(); onIdle = await widget.onPressed!(); _toDefault(); if (onIdle != null && (onIdle is VoidCallback || onIdle is FormFieldValidator)) { onIdle(); } } } void _toProcessing() { setState(() { _state = EasyButtonState.loading; }); } void _toDefault() { if (mounted) { setState(() { _state = EasyButtonState.idle; }); } else { _state = EasyButtonState.idle; } } void _forward(AnimationStatusListener stateListener) { double initialWidth = _globalKey.currentContext!.size!.width; double initialBorderRadius = widget.borderRadius; double targetWidth = _height; double targetBorderRadius = _height / 2; _animController = AnimationController(duration: _duration, vsync: this); _anim = Tween(begin: 0.0, end: 1.0).animate(_animController) ..addListener(() { setState(() { _width = initialWidth - ((initialWidth - targetWidth) * _anim!.value); _borderRadius = initialBorderRadius - ((initialBorderRadius - targetBorderRadius) * _anim!.value); }); }) ..addStatusListener(stateListener); _animController.forward(); } void _reverse() { _animController.reverse(); } } /// end_library_part /// begin_example_part void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Loading Button', debugShowCheckedModeBanner: false, theme: ThemeData( primarySwatch: Colors.blue, ), home: const MyHomePage(title: 'Flutter Loading Button'), ); } } class MyHomePage extends StatefulWidget { const MyHomePage({Key? key, required this.title}) : super(key: key); final String title; @override State<MyHomePage> createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { @override Widget build(BuildContext context) { onButtonPressed() async { await Future.delayed(const Duration(milliseconds: 3000), () => 42); // After [onPressed], it will trigger animation running backwards, from end to beginning return () { // Optional returns is returning a VoidCallback that will be called // after the animation is stopped at the beginning. // A best practice would be to do time-consuming task in [onPressed], // and do page navigation in the returned VoidCallback. // So that user won't missed out the reverse animation. }; } return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ const SizedBox( height: 15, ), const Text( 'Elevated Button', ), const SizedBox( height: 5, ), EasyButton( idleStateWidget: const Text( 'Elevated Button', style: TextStyle( color: Colors.white, ), ), loadingStateWidget: const CircularProgressIndicator( strokeWidth: 3.0, valueColor: AlwaysStoppedAnimation<Color>( Colors.white, ), ), useEqualLoadingStateWidgetDimension: true, useWidthAnimation: false, width: 150.0, height: 40.0, borderRadius: 4.0, elevation: 2.0, contentGap: 6.0, buttonColor: Colors.blueAccent, onPressed: onButtonPressed, ), const SizedBox( height: 15, ), const Text( 'Elevated Button - Animated', ), const SizedBox( height: 5, ), EasyButton( idleStateWidget: const Text( 'Elevated Button', style: TextStyle( color: Colors.white, ), ), loadingStateWidget: const CircularProgressIndicator( strokeWidth: 3.0, valueColor: AlwaysStoppedAnimation<Color>( Colors.white, ), ), useWidthAnimation: true, width: 150.0, height: 40.0, borderRadius: 4.0, contentGap: 6.0, buttonColor: Colors.blueAccent, onPressed: onButtonPressed, ), const SizedBox( height: 15, ), const Text( 'Outlined Button', ), const SizedBox( height: 5, ), EasyButton( type: EasyButtonType.outlined, idleStateWidget: const Text( 'Outlined Button', style: TextStyle( color: Colors.blueAccent, ), ), loadingStateWidget: const CircularProgressIndicator( strokeWidth: 3.0, valueColor: AlwaysStoppedAnimation<Color>( Colors.blueAccent, ), ), useEqualLoadingStateWidgetDimension: true, useWidthAnimation: false, width: 150.0, height: 40.0, borderRadius: 4.0, contentGap: 6.0, onPressed: onButtonPressed, ), const SizedBox( height: 15, ), const Text( 'Outlined Button - Animated', ), const SizedBox( height: 5, ), EasyButton( type: EasyButtonType.outlined, idleStateWidget: const Text( 'Outlined Button', style: TextStyle( color: Colors.blueAccent, ), ), loadingStateWidget: const CircularProgressIndicator( strokeWidth: 3.0, valueColor: AlwaysStoppedAnimation<Color>( Colors.blueAccent, ), ), useWidthAnimation: true, width: 150.0, height: 40.0, borderRadius: 4.0, contentGap: 6.0, onPressed: onButtonPressed, ), const SizedBox( height: 15, ), const Text( 'Text Button', ), const SizedBox( height: 5, ), EasyButton( type: EasyButtonType.text, idleStateWidget: const Text( 'Text Button', style: TextStyle( color: Colors.blueAccent, ), ), loadingStateWidget: const CircularProgressIndicator( strokeWidth: 3.0, valueColor: AlwaysStoppedAnimation<Color>( Colors.blueAccent, ), ), useEqualLoadingStateWidgetDimension: true, useWidthAnimation: false, width: 150.0, height: 28.0, borderRadius: 4.0, onPressed: onButtonPressed, ), const SizedBox( height: 15, ), const Text( 'Elevated Button Fullwidth', ), const SizedBox( height: 5, ), EasyButton( idleStateWidget: const Text( 'Elevated Button Fullwidth', style: TextStyle( color: Colors.white, ), ), loadingStateWidget: const CircularProgressIndicator( strokeWidth: 3.0, valueColor: AlwaysStoppedAnimation<Color>( Colors.white, ), ), useEqualLoadingStateWidgetDimension: true, useWidthAnimation: false, width: double.infinity, height: 40.0, contentGap: 6.0, buttonColor: Colors.blueAccent, onPressed: onButtonPressed, ), const SizedBox( height: 15, ), const Text( 'Elevated Button Fullwidth - Animated', ), const SizedBox( height: 5, ), EasyButton( idleStateWidget: const Text( 'Elevated Button Fullwidth', style: TextStyle( color: Colors.white, ), ), loadingStateWidget: const CircularProgressIndicator( strokeWidth: 3.0, valueColor: AlwaysStoppedAnimation<Color>( Colors.white, ), ), useWidthAnimation: true, width: double.infinity, height: 40.0, contentGap: 6.0, buttonColor: Colors.blueAccent, onPressed: onButtonPressed, ), ], ), ), // This trailing comma makes auto-formatting nicer for build methods. ); } } /// end_example_part