Created
July 13, 2024 13:53
-
-
Save Sp4Rx/74d3a9a9dc80c73212cdda5091523fc7 to your computer and use it in GitHub Desktop.
Reusable App Bar and Scafold in Flutter (Pseudo code only)
This file contains hidden or 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 characters
| class AppAppBar extends StatelessWidget implements PreferredSizeWidget { | |
| final WidgetBuilder? secondaryAction; | |
| final bool showBackButton; | |
| final String title; | |
| final VoidCallback? onBackPressed; | |
| final String? popScopeDescription; | |
| /// Called when the pop scope is invoked and yes pressed after showYesNoDialog | |
| final VoidCallback? onPopScopeDiscard; | |
| const AppAppBar({ | |
| super.key, | |
| this.secondaryAction, | |
| this.showBackButton = true, | |
| this.title = '', | |
| this.onBackPressed, | |
| this.popScopeDescription, | |
| this.onPopScopeDiscard, | |
| }); | |
| @override | |
| Widget build(BuildContext context) { | |
| final description = popScopeDescription; | |
| if (description != null && description.isNotEmpty) { | |
| return PopScope( | |
| canPop: false, | |
| onPopInvoked: (didPop) async { | |
| if (didPop) { | |
| return; | |
| } | |
| final result = await showYesNoDialog( | |
| context: context, | |
| title: 'Discard', | |
| subTitle: description, | |
| ); | |
| if (result && context.mounted) { | |
| onPopScopeDiscard?.call(); | |
| Navigator.pop(context); | |
| } | |
| }, | |
| child: _buildWidget(context)); | |
| } | |
| return _buildWidget(context); | |
| } | |
| @override | |
| Size get preferredSize => const Size.fromHeight(kToolbarHeight); | |
| Widget _buildWidget(BuildContext context) { | |
| return Padding( | |
| padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top + 16, left: 16, right: 16), | |
| child: Row( | |
| mainAxisAlignment: MainAxisAlignment.spaceBetween, | |
| children: [ | |
| Row( | |
| children: [ | |
| Visibility( | |
| visible: showBackButton, | |
| maintainAnimation: title.isEmpty, | |
| maintainSize: title.isEmpty, | |
| maintainState: title.isEmpty, | |
| child: TransParentRoundIconButton( | |
| Icons.arrow_back, | |
| onPressed: () { | |
| final tempOnBackPressed = onBackPressed; | |
| tempOnBackPressed != null ? tempOnBackPressed.call() : Navigator.maybePop(context); | |
| }, | |
| ), | |
| ), | |
| if (title.isNotEmpty) | |
| Padding( | |
| padding: const EdgeInsets.only(left: 8), | |
| child: Text(title), | |
| ), | |
| ], | |
| ), | |
| if (secondaryAction != null) secondaryAction!(context), | |
| ], | |
| ), | |
| ); | |
| } | |
| } |
This file contains hidden or 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 characters
| class AppScaffold extends StatelessWidget { | |
| final Widget? background; | |
| final Widget? body; | |
| final WidgetBuilder? secondaryAction; | |
| final bool showAppBar; | |
| final bool showBackground; | |
| final Widget? bottomNavigationBar; | |
| final bool showBackButton; | |
| final String title; | |
| final VoidCallback? onBackPressed; | |
| final String? popScopeDescription; | |
| final VoidCallback? onPopScopeDiscard; | |
| final bool? extendBody; | |
| const AppScaffold({ | |
| super.key, | |
| this.background, | |
| this.body, | |
| this.secondaryAction, | |
| this.showAppBar = true, | |
| this.showBackground = true, | |
| this.showBackButton = true, | |
| this.bottomNavigationBar, | |
| this.title = '', | |
| this.onBackPressed, | |
| this.popScopeDescription, | |
| this.onPopScopeDiscard, | |
| this.extendBody, | |
| }); | |
| @override | |
| Widget build(BuildContext context) { | |
| return Scaffold( | |
| appBar: showAppBar | |
| ? AppAppBar( | |
| secondaryAction: secondaryAction, | |
| showBackButton: showBackButton, | |
| title: title, | |
| onBackPressed: onBackPressed, | |
| popScopeDescription: popScopeDescription, | |
| onPopScopeDiscard: onPopScopeDiscard, | |
| ) | |
| : null, | |
| bottomNavigationBar: bottomNavigationBar, | |
| extendBody: extendBody ?? true, | |
| extendBodyBehindAppBar: true, | |
| backgroundColor: Colors.transparent, | |
| body: Stack( | |
| children: [ | |
| if (showBackground) (background != null) ? background! : const TopGradient(), | |
| if (body != null) body!, | |
| ], | |
| ), | |
| ); | |
| } | |
| } |
This file contains hidden or 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 characters
| //The `secondaryAction` has a builder pattern so that we can use bloc builder only for this button state updates | |
| AppScaffold( | |
| secondaryAction: (context) => BlocBuilder<SomeBloc, BlocState>( | |
| buildWhen: (previous, current) => current is BlocSuccessState, | |
| builder: (context, state) { | |
| return Visibility( | |
| visible: context.read<SomeBloc>().data.isNotEmpty ?? false, | |
| child: TransParentRoundIconButton( | |
| Icons.check, | |
| onPressed: () => _onConfirm(context), | |
| ), | |
| ); | |
| }),); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment