From 440748a1b3cd5d6cfd20e19630e1f3a647c00a61 Mon Sep 17 00:00:00 2001 From: Feichtmeier Date: Tue, 20 Sep 2022 19:06:12 +0200 Subject: [PATCH] YaruCompactLayout: simplify and remove appbar mode - as discussed in https://github.com/ubuntu/yaru_widgets.dart/issues/211 the NarrowLayout looks different than the WideLayout and also has not much sense for when there are more than 3 or 4 items. The NarrowLayout is also bad for mouse travel on the desktop - thus this commit removes the layout builder inside compact layout which still leaves the compact layout with three possible widths modes Closes https://github.com/ubuntu/yaru_widgets.dart/issues/211 --- .../pages/layouts/yaru_compact_layout.dart | 116 +++++++++---- lib/src/pages/layouts/yaru_narrow_layout.dart | 84 ---------- lib/src/pages/layouts/yaru_wide_layout.dart | 154 ------------------ lib/yaru_widgets.dart | 2 - 4 files changed, 84 insertions(+), 272 deletions(-) delete mode 100644 lib/src/pages/layouts/yaru_narrow_layout.dart delete mode 100644 lib/src/pages/layouts/yaru_wide_layout.dart diff --git a/lib/src/pages/layouts/yaru_compact_layout.dart b/lib/src/pages/layouts/yaru_compact_layout.dart index 30552b32d..fde2f01bd 100644 --- a/lib/src/pages/layouts/yaru_compact_layout.dart +++ b/lib/src/pages/layouts/yaru_compact_layout.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:yaru/yaru.dart'; import 'package:yaru_widgets/yaru_widgets.dart'; /// A responsive layout switching between [YaruWideLayout] @@ -7,20 +8,16 @@ class YaruCompactLayout extends StatefulWidget { const YaruCompactLayout({ Key? key, required this.pageItems, - this.narrowLayoutMaxWidth = 600, this.showSelectedLabels = true, this.showUnselectedLabels = true, this.labelType = NavigationRailLabelType.none, - this.bottomNavigationBarType = BottomNavigationBarType.fixed, this.extendNavigationRail = false, + this.initialIndex = 0, }) : super(key: key); /// The list of [YaruPageItem] has to be provided. final List pageItems; - /// The max width after the layout switches to the [YaruWideLayout], defaults to 600. - final double narrowLayoutMaxWidth; - /// Optional bool to hide selected labels in the [BottomNavigationBar] final bool showSelectedLabels; @@ -30,50 +27,105 @@ class YaruCompactLayout extends StatefulWidget { /// Optionally control the labels of the [NavigationRail] final NavigationRailLabelType labelType; - /// Optionally control the click behavior of the [BottomNavigationBar] - final BottomNavigationBarType bottomNavigationBarType; - /// Defines if the labels are shown right to the icon /// of the [NavigationRail] in the wide layout final bool extendNavigationRail; + /// The index of the [YaruPageItem] that is selected from [pageItems] + final int initialIndex; + @override State createState() => _YaruCompactLayoutState(); } class _YaruCompactLayoutState extends State { - var _index = -1; - var _previousIndex = 0; + late int _index; - void _setIndex(int index) { - _previousIndex = _index; - _index = index; + @override + void initState() { + _index = widget.initialIndex; + super.initState(); } @override Widget build(BuildContext context) { + final unselectedTextColor = + Theme.of(context).colorScheme.onSurface.withOpacity(0.8); + final selectedTextColor = Theme.of(context).colorScheme.onSurface; return SafeArea( child: Scaffold( - body: LayoutBuilder( - builder: (context, constraints) => - constraints.maxWidth > widget.narrowLayoutMaxWidth - ? YaruWideLayout( - labelType: widget.labelType, - pageItems: widget.pageItems, - initialIndex: _index == -1 ? _previousIndex : _index, - onSelected: _setIndex, - extended: widget.labelType == NavigationRailLabelType.none - ? widget.extendNavigationRail - : false, - ) - : YaruNarrowLayout( - showSelectedLabels: widget.showSelectedLabels, - showUnselectedLabels: widget.showUnselectedLabels, - bottomNavigationBarType: widget.bottomNavigationBarType, - pageItems: widget.pageItems, - initialIndex: _index == -1 ? _previousIndex : _index, - onSelected: _setIndex, + body: Row( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + SingleChildScrollView( + child: IntrinsicHeight( + child: NavigationRail( + extended: widget.labelType == NavigationRailLabelType.none + ? widget.extendNavigationRail + : false, + unselectedIconTheme: IconThemeData( + color: unselectedTextColor, + ), + indicatorColor: + Theme.of(context).colorScheme.onSurface.withOpacity(0.1), + selectedIconTheme: IconThemeData( + color: selectedTextColor, + ), + selectedLabelTextStyle: TextStyle( + overflow: TextOverflow.ellipsis, + color: selectedTextColor, + fontSize: 13, + fontWeight: FontWeight.w500, + ), + unselectedLabelTextStyle: TextStyle( + color: unselectedTextColor, + overflow: TextOverflow.ellipsis, + fontSize: 13, + fontWeight: FontWeight.w500, + ), + backgroundColor: Theme.of(context).colorScheme.background, + selectedIndex: _index, + onDestinationSelected: (index) { + setState(() => _index = index); + }, + labelType: widget.labelType, + destinations: widget.pageItems + .map( + (pageItem) => NavigationRailDestination( + icon: pageItem.itemWidget ?? Icon(pageItem.iconData), + selectedIcon: pageItem.selectedItemWidget ?? + pageItem.itemWidget ?? + (pageItem.selectedIconData != null + ? Icon(pageItem.selectedIconData) + : Icon(pageItem.iconData)), + label: pageItem.titleBuilder(context), + ), + ) + .toList(), + ), + ), + ), + const VerticalDivider(thickness: 1, width: 1), + Expanded( + child: Theme( + data: Theme.of(context).copyWith( + pageTransitionsTheme: YaruPageTransitionsTheme.vertical, + ), + child: Navigator( + pages: [ + MaterialPage( + key: ValueKey(_index), + child: widget.pageItems.length > _index + ? widget.pageItems[_index].builder(context) + : widget.pageItems[0].builder(context), ), + ], + onPopPage: (route, result) => route.didPop(result), + ), + ), + ) + ], ), ), ); diff --git a/lib/src/pages/layouts/yaru_narrow_layout.dart b/lib/src/pages/layouts/yaru_narrow_layout.dart deleted file mode 100644 index 101c4946b..000000000 --- a/lib/src/pages/layouts/yaru_narrow_layout.dart +++ /dev/null @@ -1,84 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:yaru_widgets/yaru_widgets.dart'; - -/// Creates a [BottomNavigationBar] wrapped inside [Column] -/// together with a [Widget] created by the [WidgetBuilder] of the selected [YaruPageItem]. -/// -class YaruNarrowLayout extends StatefulWidget { - /// The list of [YaruPageItem] which is used to create the views. - final List pageItems; - - /// The index of the item that should be selected when the [State] of [YaruNarrowLayout] is initialized. - final int initialIndex; - - /// Optional callback that returns an index when the page changes. - final ValueChanged? onSelected; - - /// Optional bool to hide selected labels in the [BottomNavigationBar] - final bool? showSelectedLabels; - - /// Optional bool to hide unselected labels in the [BottomNavigationBar] - final bool? showUnselectedLabels; - - /// Optionally control the click behavior of the [BottomNavigationBar] - final BottomNavigationBarType bottomNavigationBarType; - - const YaruNarrowLayout({ - Key? key, - required this.pageItems, - required this.initialIndex, - required this.onSelected, - this.showSelectedLabels = true, - this.showUnselectedLabels = true, - this.bottomNavigationBarType = BottomNavigationBarType.fixed, - }) : super(key: key); - - @override - _YaruNarrowLayoutState createState() => _YaruNarrowLayoutState(); -} - -class _YaruNarrowLayoutState extends State { - late int _selectedIndex; - @override - void initState() { - _selectedIndex = widget.initialIndex; - super.initState(); - } - - @override - Widget build(BuildContext context) { - return SafeArea( - child: Scaffold( - body: widget.pageItems[_selectedIndex].builder(context), - bottomNavigationBar: BottomNavigationBar( - type: widget.bottomNavigationBarType, - showSelectedLabels: widget.showSelectedLabels, - showUnselectedLabels: widget.showUnselectedLabels, - items: [ - for (final pageItem in widget.pageItems) - BottomNavigationBarItem( - icon: pageItem.itemWidget ?? Icon(pageItem.iconData), - activeIcon: pageItem.selectedItemWidget ?? - pageItem.itemWidget ?? - (pageItem.selectedIconData != null - ? Icon(pageItem.selectedIconData) - : Icon(pageItem.iconData)), - label: convertWidgetToString( - pageItem.titleBuilder(context), - ), - ) - ], - currentIndex: _selectedIndex, - onTap: (index) { - widget.onSelected!(index); - setState(() => _selectedIndex = index); - }, - ), - ), - ); - } - - String convertWidgetToString(Widget widget) { - return widget is Text && widget.data != null ? widget.data! : ''; - } -} diff --git a/lib/src/pages/layouts/yaru_wide_layout.dart b/lib/src/pages/layouts/yaru_wide_layout.dart deleted file mode 100644 index 5416c91a6..000000000 --- a/lib/src/pages/layouts/yaru_wide_layout.dart +++ /dev/null @@ -1,154 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:yaru/yaru.dart'; -import 'package:yaru_widgets/yaru_widgets.dart'; - -/// Creates a [NavigationRail] wrapped inside [Row] -/// together with a [Widget] created by the [WidgetBuilder] of the selected [YaruPageItem]. -/// -class YaruWideLayout extends StatefulWidget { - /// The list of [YaruPageItem] which is used to create the views. - final List pageItems; - - /// The index of the item that should be selected when the [State] of [YaruNarrowLayout] is initialized. - final int initialIndex; - - /// An optional [ScrollController] - if not provided the [YaruWideLayout] will create a new one for - /// the [NavigationRail] - final ScrollController? scrollController; - - /// Optional callback that returns an index when the page changes. - final ValueChanged? onSelected; - - /// Optionally control the labels of the [NavigationRail] - final NavigationRailLabelType? labelType; - - /// Defines if the labels are shown right to the icon - /// of the [NavigationRail] - final bool extended; - - const YaruWideLayout({ - Key? key, - required this.pageItems, - required this.initialIndex, - this.scrollController, - this.labelType = NavigationRailLabelType.selected, - this.extended = false, - required this.onSelected, - }) : super(key: key); - - @override - _YaruWideLayoutState createState() => _YaruWideLayoutState(); -} - -class _YaruWideLayoutState extends State { - late int _selectedIndex; - - @override - void initState() { - _selectedIndex = widget.initialIndex; - super.initState(); - } - - @override - Widget build(BuildContext context) { - final unselectedTextColor = - Theme.of(context).colorScheme.onSurface.withOpacity(0.8); - final selectedTextColor = Theme.of(context).colorScheme.onSurface; - return LayoutBuilder( - builder: (context, constraint) { - return SafeArea( - child: Scaffold( - body: Row( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - SizedBox( - height: MediaQuery.of(context).size.height, - child: SingleChildScrollView( - controller: widget.scrollController ?? ScrollController(), - child: ConstrainedBox( - constraints: - BoxConstraints(minHeight: constraint.maxHeight), - child: IntrinsicHeight( - child: NavigationRail( - extended: - widget.labelType == NavigationRailLabelType.none - ? widget.extended - : false, - unselectedIconTheme: IconThemeData( - color: unselectedTextColor, - ), - indicatorColor: Theme.of(context) - .colorScheme - .onSurface - .withOpacity(0.1), - selectedIconTheme: IconThemeData( - color: selectedTextColor, - ), - selectedLabelTextStyle: TextStyle( - overflow: TextOverflow.ellipsis, - color: selectedTextColor, - fontSize: 13, - fontWeight: FontWeight.w500, - ), - unselectedLabelTextStyle: TextStyle( - color: unselectedTextColor, - overflow: TextOverflow.ellipsis, - fontSize: 13, - fontWeight: FontWeight.w500, - ), - backgroundColor: - Theme.of(context).colorScheme.background, - selectedIndex: _selectedIndex, - onDestinationSelected: (index) { - widget.onSelected!(index); - setState(() => _selectedIndex = index); - }, - labelType: widget.labelType, - destinations: widget.pageItems - .map( - (pageItem) => NavigationRailDestination( - icon: pageItem.itemWidget ?? - Icon(pageItem.iconData), - selectedIcon: pageItem.selectedItemWidget ?? - pageItem.itemWidget ?? - (pageItem.selectedIconData != null - ? Icon(pageItem.selectedIconData) - : Icon(pageItem.iconData)), - label: pageItem.titleBuilder(context), - ), - ) - .toList(), - ), - ), - ), - ), - ), - const VerticalDivider(thickness: 1, width: 1), - Expanded( - child: Theme( - data: Theme.of(context).copyWith( - pageTransitionsTheme: YaruPageTransitionsTheme.vertical, - ), - child: Navigator( - pages: [ - MaterialPage( - key: ValueKey(_selectedIndex), - child: widget.pageItems.length > _selectedIndex - ? widget.pageItems[_selectedIndex] - .builder(context) - : widget.pageItems[0].builder(context), - ), - ], - onPopPage: (route, result) => route.didPop(result), - ), - ), - ) - ], - ), - ), - ); - }, - ); - } -} diff --git a/lib/yaru_widgets.dart b/lib/yaru_widgets.dart index 9c9f340db..7b78c81c0 100644 --- a/lib/yaru_widgets.dart +++ b/lib/yaru_widgets.dart @@ -24,10 +24,8 @@ export 'src/pages/yaru_tabbed_page.dart'; // Pages layouts export 'src/pages/layouts/yaru_compact_layout.dart'; export 'src/pages/layouts/yaru_master_detail_page.dart'; -export 'src/pages/layouts/yaru_narrow_layout.dart'; export 'src/pages/layouts/yaru_page_item.dart'; export 'src/pages/layouts/yaru_page_item_title.dart'; -export 'src/pages/layouts/yaru_wide_layout.dart'; // Pages rows export 'src/pages/rows/yaru_checkbox_row.dart';