diff --git a/lib/ui/screens/editorial/editorial_screen.dart b/lib/ui/screens/editorial/editorial_screen.dart index b2f342e2..20f0163c 100644 --- a/lib/ui/screens/editorial/editorial_screen.dart +++ b/lib/ui/screens/editorial/editorial_screen.dart @@ -38,10 +38,9 @@ part 'widgets/_title_text.dart'; part 'widgets/_top_illustration.dart'; class WonderEditorialScreen extends StatefulWidget { - const WonderEditorialScreen(this.data, {Key? key, required this.onScroll, required this.contentPadding}) - : super(key: key); + const WonderEditorialScreen(this.data, {Key? key, required this.contentPadding}) : super(key: key); final WonderData data; - final void Function(double scrollPos) onScroll; + //final void Function(double scrollPos) onScroll; final EdgeInsets contentPadding; @override @@ -62,7 +61,6 @@ class _WonderEditorialScreenState extends State { /// Various [ValueListenableBuilders] are mapped to the _scrollPos and will rebuild when it changes void _handleScrollChanged() { _scrollPos.value = _scroller.position.pixels; - widget.onScroll.call(_scrollPos.value); } @override @@ -168,16 +166,17 @@ class _WonderEditorialScreenState extends State { ), /// Home Btn - AnimatedBuilder( - animation: _scroller, - builder: (_, child) { - return AnimatedOpacity( - opacity: _scrollPos.value > 0 ? 0 : 1, - duration: $styles.times.med, - child: child, - ); - }, - child: AppHeader(backIcon: AppIcons.north, isTransparent: true)), + /// TODO: Decide when to show the back btn, probably whenever in tab view? This should be passed down from above somewhere... + // AnimatedBuilder( + // animation: _scroller, + // builder: (_, child) { + // return AnimatedOpacity( + // opacity: _scrollPos.value > 0 ? 0 : 1, + // duration: $styles.times.med, + // child: child, + // ); + // }, + // child: AppHeader(backIcon: AppIcons.north, isTransparent: true)), ], ), ), diff --git a/lib/ui/screens/wonder_details/wonder_details_tab_menu.dart b/lib/ui/screens/wonder_details/wonder_details_tab_menu.dart index 95c6e13b..0ffeac4f 100644 --- a/lib/ui/screens/wonder_details/wonder_details_tab_menu.dart +++ b/lib/ui/screens/wonder_details/wonder_details_tab_menu.dart @@ -3,6 +3,9 @@ import 'package:wonders/common_libs.dart'; class WonderDetailsTabMenu extends StatelessWidget { static double bottomPadding = 0; static double buttonInset = 12; + static const double homeBtnSize = 74; + static double get minTabSize => 25; + static const double maxTabSize = 100; const WonderDetailsTabMenu( {Key? key, @@ -21,92 +24,107 @@ class WonderDetailsTabMenu extends StatelessWidget { @override Widget build(BuildContext context) { Color iconColor = showBg ? $styles.colors.black : $styles.colors.white; - const double homeBtnSize = 74; + + final availableSize = ((isVertical ? context.heightPx : context.widthPx) - homeBtnSize - $styles.insets.md); + final double tabBtnSize = (availableSize / 4).clamp(minTabSize, maxTabSize); + final double homeBtnBorderSize = showBg ? 6 : 2; + final double gapAmt = max(0, tabBtnSize - homeBtnSize); // Use SafeArea padding if its more than the default padding. bottomPadding = max(context.mq.padding.bottom, $styles.insets.xs * 1.5); - return Stack( - children: [ - /// Background, animates in and out based on `showBg` - Positioned.fill( - child: AnimatedOpacity( - duration: $styles.times.fast, - opacity: showBg ? 1 : 0, - child: Padding( - padding: EdgeInsets.only( - top: isVertical ? context.mq.viewPadding.top : buttonInset, - right: isVertical ? buttonInset : 0, - ), - child: Container( - decoration: BoxDecoration( - color: $styles.colors.offWhite, - borderRadius: isVertical ? BorderRadius.only(topRight: Radius.circular(32)) : null, + return Padding( + padding: EdgeInsets.only( + top: isVertical ? context.mq.viewPadding.top : buttonInset, + right: isVertical ? buttonInset : 0, + ), + child: Stack( + children: [ + /// Background, animates in and out based on `showBg` + Positioned.fill( + child: AnimatedOpacity( + duration: $styles.times.fast, + opacity: showBg ? 1 : 0, + child: Padding( + padding: EdgeInsets.only(right: isVertical ? buttonInset : 0, top: isVertical ? 0 : buttonInset), + child: Container( + decoration: BoxDecoration( + color: $styles.colors.white, + borderRadius: isVertical ? BorderRadius.only(topRight: Radius.circular(32)) : null, + ), ), ), ), ), - ), - /// Buttons - /// A Stack with a row or column of tabButtons, and an illustrated homeButton sitting on top. - Padding( - padding: EdgeInsets.only(left: $styles.insets.sm, right: $styles.insets.xxs, bottom: bottomPadding), - child: Stack( - children: [ - SizedBox( - width: isVertical ? null : double.infinity, - height: isVertical ? double.infinity : null, - child: FocusTraversalGroup( - child: Flex( - direction: axis, - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: isVertical ? CrossAxisAlignment.start : CrossAxisAlignment.center, - mainAxisSize: MainAxisSize.min, - children: [ - /// Home btn - _WonderHomeBtn( - size: homeBtnSize, - wonderType: wonderType, - borderSize: showBg ? 6 : 2, - ), + /// Buttons + /// A Stack with a row or column of tabButtons, and an illustrated homeButton sitting on top. + Padding( + padding: EdgeInsets.only(left: $styles.insets.xs * 1.5, right: $styles.insets.xxs, bottom: bottomPadding), + child: Stack( + children: [ + SizedBox( + width: isVertical ? null : double.infinity, + height: isVertical ? double.infinity : null, + child: FocusTraversalGroup( + child: Flex( + direction: axis, + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + /// Home btn + _WonderHomeBtn( + size: homeBtnSize, + wonderType: wonderType, + borderSize: homeBtnBorderSize, + ), + Gap(gapAmt), - /// Tabs - _TabBtn( - 0, - tabController, - iconImg: 'editorial', - label: $strings.wonderDetailsTabLabelInformation, - color: iconColor, - axis: axis, - ), - _TabBtn( - 1, - tabController, - iconImg: 'photos', - label: $strings.wonderDetailsTabLabelImages, - color: iconColor, - axis: axis, - ), - _TabBtn( - 2, - tabController, - iconImg: 'artifacts', - label: $strings.wonderDetailsTabLabelArtifacts, - color: iconColor, - axis: axis, - ), - _TabBtn(3, tabController, + /// Tabs + _TabBtn( + 0, + tabController, + iconImg: 'editorial', + label: $strings.wonderDetailsTabLabelInformation, + color: iconColor, + axis: axis, + mainAxisSize: tabBtnSize, + ), + _TabBtn( + 1, + tabController, + iconImg: 'photos', + label: $strings.wonderDetailsTabLabelImages, + color: iconColor, + axis: axis, + mainAxisSize: tabBtnSize, + ), + _TabBtn( + 2, + tabController, + iconImg: 'artifacts', + label: $strings.wonderDetailsTabLabelArtifacts, + color: iconColor, + axis: axis, + mainAxisSize: tabBtnSize, + ), + _TabBtn( + 3, + tabController, iconImg: 'timeline', label: $strings.wonderDetailsTabLabelEvents, color: iconColor, - axis: axis), - ], + axis: axis, + mainAxisSize: tabBtnSize, + ), + ], + ), ), ), - ), - ], + ], + ), ), - ), - ], + ], + ), ); } } @@ -123,7 +141,7 @@ class _WonderHomeBtn extends StatelessWidget { Widget build(BuildContext context) { return CircleBtn( onPressed: () => Navigator.of(context).pop(), - bgColor: $styles.colors.offWhite, + bgColor: $styles.colors.white, semanticLabel: $strings.wonderDetailsTabSemanticBack, child: AnimatedContainer( curve: Curves.easeOut, @@ -150,10 +168,9 @@ class _TabBtn extends StatelessWidget { required this.color, required this.label, required this.axis, + required this.mainAxisSize, }) : super(key: key); - static const double minSize = 30; - static const double maxSize = 100; static const double crossBtnSize = 60; final int index; @@ -162,30 +179,35 @@ class _TabBtn extends StatelessWidget { final Color color; final String label; final Axis axis; + final double mainAxisSize; bool get _isVertical => axis == Axis.vertical; @override Widget build(BuildContext context) { + return _isVertical + ? SizedBox(height: mainAxisSize, width: crossBtnSize, child: Placeholder()) + : SizedBox(height: crossBtnSize, width: mainAxisSize, child: Placeholder()); bool selected = tabController.index == index; final MaterialLocalizations localizations = MaterialLocalizations.of(context); final iconImgPath = '${ImagePaths.common}/tab-$iconImg${selected ? '-active' : ''}.png'; String tabLabel = localizations.tabLabel(tabIndex: index + 1, tabCount: tabController.length); tabLabel = '$label: $tabLabel'; - final double mainBtnSize = (((_isVertical ? context.heightPx : context.widthPx) - 74) / 5).clamp(minSize, maxSize); - final double iconSize = min(mainBtnSize, 32); - print(context.heightPx); + final double iconSize = min(mainAxisSize, 32); + return MergeSemantics( child: Semantics( selected: selected, label: tabLabel, child: ExcludeSemantics( child: AppBtn.basic( - padding: EdgeInsets.only(top: $styles.insets.md + $styles.insets.xs, bottom: $styles.insets.sm), + padding: _isVertical + ? EdgeInsets.zero + : EdgeInsets.only(top: $styles.insets.md + $styles.insets.xs, bottom: $styles.insets.sm), onPressed: () => tabController.index = index, semanticLabel: label, - minimumSize: _isVertical ? Size(crossBtnSize, mainBtnSize) : Size(mainBtnSize, crossBtnSize), + minimumSize: _isVertical ? Size(crossBtnSize, mainAxisSize) : Size(mainAxisSize, crossBtnSize), // Image icon child: Image.asset(iconImgPath, height: iconSize, width: iconSize, color: selected ? null : color), ), diff --git a/lib/ui/screens/wonder_details/wonders_details_screen.dart b/lib/ui/screens/wonder_details/wonders_details_screen.dart index 2abe0c49..e8863743 100644 --- a/lib/ui/screens/wonder_details/wonders_details_screen.dart +++ b/lib/ui/screens/wonder_details/wonders_details_screen.dart @@ -25,7 +25,6 @@ class _WonderDetailsScreenState extends State )..addListener(_handleTabChanged); AnimationController? _fade; - final _detailsHasScrolled = ValueNotifier(false); double? _tabBarSize; bool _useNavRail = false; @@ -40,8 +39,6 @@ class _WonderDetailsScreenState extends State setState(() {}); } - void _handleDetailsScrolled(double scrollPos) => _detailsHasScrolled.value = scrollPos > 0; - void _handleTabMenuSized(Size size) { setState(() { _tabBarSize = (_useNavRail ? size.width : size.height) - WonderDetailsTabMenu.buttonInset; @@ -50,7 +47,7 @@ class _WonderDetailsScreenState extends State @override Widget build(BuildContext context) { - _useNavRail = context.isLandscape && context.heightPx < 900; + _useNavRail = context.isLandscape && context.heightPx > 250; final wonder = wondersLogic.getData(widget.type); int tabIndex = _tabController.index; @@ -65,7 +62,7 @@ class _WonderDetailsScreenState extends State LazyIndexedStack( index: _tabController.index, children: [ - WonderEditorialScreen(wonder, contentPadding: menuPadding, onScroll: _handleDetailsScrolled), + WonderEditorialScreen(wonder, contentPadding: menuPadding), PhotoGallery(collectionId: wonder.unsplashCollectionId, wonderType: wonder.type), ArtifactCarouselScreen(type: wonder.type, contentPadding: menuPadding), WonderEvents(type: widget.type, contentPadding: menuPadding), @@ -75,16 +72,13 @@ class _WonderDetailsScreenState extends State /// Tab menu Align( alignment: _useNavRail ? Alignment.centerLeft : Alignment.bottomCenter, - child: ValueListenableBuilder( - valueListenable: _detailsHasScrolled, - builder: (_, value, ___) => MeasurableWidget( - onChange: _handleTabMenuSized, - child: WonderDetailsTabMenu( - tabController: _tabController, - wonderType: wonder.type, - showBg: showTabBarBg, - axis: _useNavRail ? Axis.vertical : Axis.horizontal), - ), + child: MeasurableWidget( + onChange: _handleTabMenuSized, + child: WonderDetailsTabMenu( + tabController: _tabController, + wonderType: wonder.type, + showBg: showTabBarBg, + axis: _useNavRail ? Axis.vertical : Axis.horizontal), ), ), ], diff --git a/pubspec.lock b/pubspec.lock index 716bfca4..ec4c9f99 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -125,10 +125,10 @@ packages: dependency: transitive description: name: characters - sha256: e6a326c8af69605aec75ed6c187d06b349707a27fbff8222ca9cc2cff167975c + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.3.0" checked_yaml: dependency: transitive description: @@ -157,10 +157,10 @@ packages: dependency: "direct main" description: name: collection - sha256: cfc915e6923fe5ce6e153b0723c753045de46de1b4d63771530504004a45fae0 + sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" url: "https://pub.dev" source: hosted - version: "1.17.0" + version: "1.17.1" convert: dependency: transitive description: @@ -564,10 +564,10 @@ packages: dependency: transitive description: name: intl - sha256: "910f85bce16fb5c6f614e117efa303e85a1731bb0081edf3604a2ae6e9a3cc91" + sha256: a3715e3bc90294e971cb7dc063fbf3cd9ee0ebf8604ffeafabd9e6f16abbdbe6 url: "https://pub.dev" source: hosted - version: "0.17.0" + version: "0.18.0" io: dependency: transitive description: @@ -580,10 +580,10 @@ packages: dependency: transitive description: name: js - sha256: "5528c2f391ededb7775ec1daa69e65a2d61276f7552de2b5f7b8d34ee9fd4ab7" + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 url: "https://pub.dev" source: hosted - version: "0.6.5" + version: "0.6.7" js_wrapping: dependency: transitive description: @@ -644,10 +644,10 @@ packages: dependency: transitive description: name: meta - sha256: "6c268b42ed578a53088d834796959e4a1814b5e9e164f147f580a386e5decf42" + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" url: "https://pub.dev" source: hosted - version: "1.8.0" + version: "1.9.1" mime: dependency: transitive description: @@ -700,10 +700,10 @@ packages: dependency: transitive description: name: path - sha256: db9d4f58c908a4ba5953fcee2ae317c94889433e5024c27ce74a37f94267945b + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" url: "https://pub.dev" source: hosted - version: "1.8.2" + version: "1.8.3" path_parsing: dependency: transitive description: @@ -1270,5 +1270,5 @@ packages: source: hosted version: "2.0.2" sdks: - dart: ">=2.19.0-0 <3.0.0" + dart: ">=3.0.0-0 <4.0.0" flutter: ">=3.7.0-0"