diff --git a/example/lib/main.dart b/example/lib/main.dart index 6c01dd96b..6345f8034 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -70,8 +70,15 @@ class _HomeState extends State { ), titleBuilder: (context, index, selected) => pageItems[index].titleBuilder(context), - pageBuilder: (context, index) => - pageItems[index].pageBuilder(context), + pageBuilder: (context, index) => YaruDetailPage( + appBar: AppBar( + leading: Navigator.of(context).canPop() + ? const YaruBackButton() + : null, + title: pageItems[index].titleBuilder(context), + ), + body: pageItems[index].pageBuilder(context), + ), appBar: AppBar( title: const Text('Example'), ), diff --git a/lib/src/pages/layouts/yaru_detail_page.dart b/lib/src/pages/layouts/yaru_detail_page.dart new file mode 100644 index 000000000..6c8dc2e15 --- /dev/null +++ b/lib/src/pages/layouts/yaru_detail_page.dart @@ -0,0 +1,92 @@ +import 'package:flutter/material.dart'; + +/// Provides the recommended layout for [YaruMasterDetailPage.pageBuilder]. +/// +/// This widget is similar to [Scaffold] with the exception that it wraps the +/// [appBar] in a [Hero] to keep it in place at the top during page transitions. +class YaruDetailPage extends StatelessWidget { + const YaruDetailPage({ + super.key, + this.appBar, + this.body, + this.floatingActionButton, + this.floatingActionButtonLocation, + this.floatingActionButtonAnimator, + this.persistentFooterButtons, + this.persistentFooterAlignment = AlignmentDirectional.centerEnd, + this.bottomNavigationBar, + this.bottomSheet, + this.backgroundColor, + this.extendBody = false, + this.extendBodyBehindAppBar = false, + }); + + /// See [Scaffold.extendBody]. + final bool extendBody; + + /// See [Scaffold.extendBodyBehindAppBar]. + final bool extendBodyBehindAppBar; + + /// See [Scaffold.appBar]. + final PreferredSizeWidget? appBar; + + /// See [Scaffold.body]. + final Widget? body; + + /// See [Scaffold.floatingActionButton]. + final Widget? floatingActionButton; + + /// See [Scaffold.floatingActionButtonLocation]. + final FloatingActionButtonLocation? floatingActionButtonLocation; + + /// See [Scaffold.floatingActionButtonAnimator]. + final FloatingActionButtonAnimator? floatingActionButtonAnimator; + + /// See [Scaffold.persistentFooterButtons]. + final List? persistentFooterButtons; + + /// See [Scaffold.persistentFooterAlignment]. + final AlignmentDirectional persistentFooterAlignment; + + /// See [Scaffold.backgroundColor]. + final Color? backgroundColor; + + /// See [Scaffold.bottomNavigationBar]. + final Widget? bottomNavigationBar; + + /// See [Scaffold.bottomSheet]. + final Widget? bottomSheet; + + PreferredSizeWidget? _buildAppBar(BuildContext context) { + if (appBar == null) return null; + + return PreferredSize( + preferredSize: Size( + 0, + Theme.of(context).appBarTheme.toolbarHeight ?? kToolbarHeight, + ), + child: Hero( + tag: '', + child: appBar!, + ), + ); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: _buildAppBar(context), + body: body, + floatingActionButton: floatingActionButton, + floatingActionButtonLocation: floatingActionButtonLocation, + floatingActionButtonAnimator: floatingActionButtonAnimator, + persistentFooterButtons: persistentFooterButtons, + persistentFooterAlignment: persistentFooterAlignment, + bottomNavigationBar: bottomNavigationBar, + bottomSheet: bottomSheet, + backgroundColor: backgroundColor, + extendBody: extendBody, + extendBodyBehindAppBar: extendBodyBehindAppBar, + ); + } +} diff --git a/lib/src/pages/layouts/yaru_landscape_layout.dart b/lib/src/pages/layouts/yaru_landscape_layout.dart index b679a61c3..81a8db8a8 100644 --- a/lib/src/pages/layouts/yaru_landscape_layout.dart +++ b/lib/src/pages/layouts/yaru_landscape_layout.dart @@ -63,79 +63,50 @@ class _YaruLandscapeLayoutState extends State { @override Widget build(BuildContext context) { - return Scaffold( - body: Column( - children: [ - SizedBox( - height: widget.appBar != null - ? Theme.of(context).appBarTheme.toolbarHeight ?? kToolbarHeight - : 0, - child: Row( - children: [ - SizedBox( - width: widget.leftPaneWidth, - child: widget.appBar, - ), - if (widget.appBar != null) - Expanded( - child: AppBar( - title: widget.titleBuilder( - context, - widget.length > _selectedIndex ? _selectedIndex : 0, - false, - ), - ), - ) - ], + return Row( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Container( + width: widget.leftPaneWidth, + decoration: BoxDecoration( + border: Border( + right: BorderSide( + width: 1, + color: Colors.black.withOpacity(0.1), + ), ), ), - Expanded( - child: Row( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - SizedBox( - width: widget.leftPaneWidth, - child: Container( - decoration: BoxDecoration( - border: Border( - right: BorderSide( - width: 1, - color: Colors.black.withOpacity(0.1), - ), - ), - ), - child: YaruPageItemListView( - length: widget.length, - selectedIndex: _selectedIndex, - onTap: _onTap, - builder: widget.tileBuilder, - ), - ), - ), - Expanded( - child: Theme( - data: Theme.of(context).copyWith( - pageTransitionsTheme: YaruPageTransitionsTheme.vertical, - ), - child: Navigator( - pages: [ - MaterialPage( - key: ValueKey(_selectedIndex), - child: widget.length > _selectedIndex - ? widget.pageBuilder(context, _selectedIndex) - : widget.pageBuilder(context, 0), - ), - ], - onPopPage: (route, result) => route.didPop(result), - ), - ), + child: Scaffold( + appBar: widget.appBar, + body: YaruPageItemListView( + length: widget.length, + selectedIndex: _selectedIndex, + onTap: _onTap, + builder: widget.tileBuilder, + ), + ), + ), + Expanded( + child: Theme( + data: Theme.of(context).copyWith( + pageTransitionsTheme: YaruPageTransitionsTheme.vertical, + ), + child: Navigator( + pages: [ + MaterialPage( + key: ValueKey(_selectedIndex), + child: widget.length > _selectedIndex + ? widget.pageBuilder(context, _selectedIndex) + : widget.pageBuilder(context, 0), ), ], + onPopPage: (route, result) => route.didPop(result), + observers: [HeroController()], ), ), - ], - ), + ), + ], ); } } diff --git a/lib/src/pages/layouts/yaru_master_detail_page.dart b/lib/src/pages/layouts/yaru_master_detail_page.dart index 1fc0c6542..523200017 100644 --- a/lib/src/pages/layouts/yaru_master_detail_page.dart +++ b/lib/src/pages/layouts/yaru_master_detail_page.dart @@ -40,12 +40,18 @@ class YaruMasterDetailPage extends StatefulWidget { final int length; /// A builder that is called for each page to build its master tile. + /// + /// See also: + /// * [YaruMasterTile] final YaruMasterDetailBuilder tileBuilder; /// A builder that is called for each page to build its title. final YaruMasterDetailBuilder titleBuilder; /// A builder that is called for each page to build its detail page. + /// + /// See also: + /// * [YaruDetailPage] final IndexedWidgetBuilder pageBuilder; /// Specifies the width of left pane. diff --git a/lib/src/pages/layouts/yaru_portrait_layout.dart b/lib/src/pages/layouts/yaru_portrait_layout.dart index b04c4274a..c9f646a24 100644 --- a/lib/src/pages/layouts/yaru_portrait_layout.dart +++ b/lib/src/pages/layouts/yaru_portrait_layout.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; import 'package:yaru/yaru.dart'; -import '../../controls/yaru_back_button.dart'; import 'yaru_master_detail_page.dart'; import 'yaru_page_item_list_view.dart'; @@ -48,26 +47,9 @@ class _YaruPortraitLayoutState extends State { setState(() => _selectedIndex = index); } - void _goBack() { - widget.onSelected(-1); - _navigator.pop(context); - } - MaterialPageRoute pageRoute(int index) { return MaterialPageRoute( - builder: (context) { - return Scaffold( - appBar: widget.appBar != null - ? AppBar( - title: widget.titleBuilder(context, index, false), - leading: YaruBackButton( - onPressed: _goBack, - ), - ) - : null, - body: SizedBox.expand(child: widget.pageBuilder(context, index)), - ); - }, + builder: (context) => widget.pageBuilder(context, index), ); } diff --git a/lib/yaru_widgets.dart b/lib/yaru_widgets.dart index 6e1362594..d2f742e62 100644 --- a/lib/yaru_widgets.dart +++ b/lib/yaru_widgets.dart @@ -17,6 +17,7 @@ export 'src/dialogs/yaru_simple_dialog.dart'; export 'src/extensions/border_radius_extension.dart'; // Pages layouts export 'src/pages/layouts/yaru_compact_layout.dart'; +export 'src/pages/layouts/yaru_detail_page.dart'; export 'src/pages/layouts/yaru_master_detail_page.dart'; export 'src/pages/layouts/yaru_master_tile.dart'; export 'src/pages/layouts/yaru_navigation_rail.dart';