From bd3a87edd9ea4de65ae5f118f0bfbd7af612049e Mon Sep 17 00:00:00 2001 From: Shawn Date: Wed, 30 Nov 2022 13:30:56 -0700 Subject: [PATCH] Polish editorial screen --- lib/ui/common/curved_clippers.dart | 10 +- .../collectible_found_screen.dart | 1 - .../screens/editorial/editorial_screen.dart | 18 +-- .../screens/editorial/widgets/_app_bar.dart | 39 ++--- .../editorial/widgets/_scrolling_content.dart | 82 ++++++----- .../editorial/widgets/_title_text.dart | 139 +++++++++--------- .../wonder_details_tab_menu.dart | 23 +-- pubspec.lock | 8 +- 8 files changed, 157 insertions(+), 163 deletions(-) diff --git a/lib/ui/common/curved_clippers.dart b/lib/ui/common/curved_clippers.dart index cd2d2921..d0bf9747 100644 --- a/lib/ui/common/curved_clippers.dart +++ b/lib/ui/common/curved_clippers.dart @@ -39,7 +39,7 @@ class ArchPoint { } List _getArchPts(Size size, ArchType type) { - double distanceFromTop = 100; + double distanceFromTop = size.width / 3; switch (type) { case ArchType.pyramid: return [ @@ -60,19 +60,19 @@ List _getArchPts(Size size, ArchType type) { case ArchType.arch: return [ ArchPoint(Offset(0, size.height)), - ArchPoint(Offset(0, distanceFromTop * 2)), + ArchPoint(Offset(0, size.width / 2)), ArchPoint(Offset(size.width / 2, 0), Offset(0, 0)), - ArchPoint(Offset(size.width, distanceFromTop * 2), Offset(size.width, 0)), + ArchPoint(Offset(size.width, size.width / 2), Offset(size.width, 0)), ArchPoint(Offset(size.width, size.height)), ]; case ArchType.wideArch: return [ ArchPoint(Offset(0, size.height)), - ArchPoint(Offset(0, distanceFromTop * 2)), + ArchPoint(Offset(0, size.width / 2)), ArchPoint(Offset(0, distanceFromTop)), ArchPoint(Offset(size.width / 2, 0), Offset(0, 0)), ArchPoint(Offset(size.width, distanceFromTop), Offset(size.width, 0)), - ArchPoint(Offset(size.width, distanceFromTop * 2)), + ArchPoint(Offset(size.width, size.width / 2)), ArchPoint(Offset(size.width, size.height)), ]; case ArchType.flatPyramid: diff --git a/lib/ui/screens/collectible_found/collectible_found_screen.dart b/lib/ui/screens/collectible_found/collectible_found_screen.dart index fe4524de..34b2b2e3 100644 --- a/lib/ui/screens/collectible_found/collectible_found_screen.dart +++ b/lib/ui/screens/collectible_found/collectible_found_screen.dart @@ -160,7 +160,6 @@ class CollectibleFoundScreen extends StatelessWidget { return AppBtn.from( text: $strings.collectibleFoundButtonViewCollection, isSecondary: true, - expand: true, onPressed: () => _handleViewCollectionPressed(context), ) .animate() diff --git a/lib/ui/screens/editorial/editorial_screen.dart b/lib/ui/screens/editorial/editorial_screen.dart index 0ede005f..6a11f2e7 100644 --- a/lib/ui/screens/editorial/editorial_screen.dart +++ b/lib/ui/screens/editorial/editorial_screen.dart @@ -5,6 +5,7 @@ import 'package:flutter/rendering.dart'; import 'package:flutter_circular_text/circular_text.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:wonders/common_libs.dart'; +import 'package:wonders/logic/common/platform_info.dart'; import 'package:wonders/logic/common/string_utils.dart'; import 'package:wonders/logic/data/wonder_data.dart'; import 'package:wonders/ui/common/app_icons.dart'; @@ -72,7 +73,9 @@ class _WonderEditorialScreenState extends State { bool shortMode = constraints.biggest.height < 700; double illustrationHeight = shortMode ? 250 : 280; double minAppBarHeight = shortMode ? 80 : 120; - double maxAppBarHeight = shortMode ? 400 : 500; + + /// Attempt to maintain a similar aspect ratio for the image within the app-bar + double maxAppBarHeight = min(context.widthPx, $styles.sizes.maxContentWidth1) * 1.5; return PopRouterOnOverScroll( controller: _scroller, @@ -82,16 +85,7 @@ class _WonderEditorialScreenState extends State { children: [ /// Background Positioned.fill( - child: ValueListenableBuilder( - valueListenable: _scrollPos, - builder: (_, value, __) { - bool showBg = value < 700; - return AnimatedContainer( - duration: $styles.times.fast, - color: widget.data.type.bgColor.withOpacity(showBg ? 1 : 0), - ); - }, - ), + child: ColoredBox(color: widget.data.type.bgColor), ), /// Top Illustration - Sits underneath the scrolling content, fades out as it scrolls @@ -112,7 +106,7 @@ class _WonderEditorialScreenState extends State { /// Scrolling content - Includes an invisible gap at the top, and then scrolls over the illustration TopCenter( child: SizedBox( - width: $styles.sizes.maxContentWidth1, + //width: $styles.sizes.maxContentWidth1, child: CustomScrollView( primary: false, controller: _scroller, diff --git a/lib/ui/screens/editorial/widgets/_app_bar.dart b/lib/ui/screens/editorial/widgets/_app_bar.dart index 365ec25e..7306d49a 100644 --- a/lib/ui/screens/editorial/widgets/_app_bar.dart +++ b/lib/ui/screens/editorial/widgets/_app_bar.dart @@ -47,28 +47,33 @@ class _AppBar extends StatelessWidget { fit: StackFit.expand, children: [ AnimatedSwitcher( - duration: $styles.times.fast * .5, + duration: $styles.times.med, child: Stack( key: ValueKey(showOverlay), fit: StackFit.expand, children: [ /// Masked image - ClipPath( - // Switch arch type to Rect if we are showing the title bar - clipper: showOverlay ? null : ArchClipper(arch), - child: ValueListenableBuilder( - valueListenable: scrollPos, - builder: (_, value, child) { - double opacity = (.4 + (value / 1500)).clamp(0, 1); - return ScalingListItem( - scrollPos: scrollPos, - child: Image.asset( - wonderType.photo1, - fit: BoxFit.cover, - opacity: AlwaysStoppedAnimation(opacity), - ), - ); - }, + Center( + child: SizedBox( + width: showOverlay ? double.infinity : $styles.sizes.maxContentWidth1, + child: ClipPath( + // Switch arch type to Rect if we are showing the title bar + clipper: showOverlay ? null : ArchClipper(arch), + child: ValueListenableBuilder( + valueListenable: scrollPos, + builder: (_, value, child) { + double opacity = (.4 + (value / 1500)).clamp(0, 1); + return ScalingListItem( + scrollPos: scrollPos, + child: Image.asset( + wonderType.photo1, + fit: BoxFit.cover, + opacity: AlwaysStoppedAnimation(opacity), + ), + ); + }, + ), + ), ), ), diff --git a/lib/ui/screens/editorial/widgets/_scrolling_content.dart b/lib/ui/screens/editorial/widgets/_scrolling_content.dart index 92e6cf69..8b3c649c 100644 --- a/lib/ui/screens/editorial/widgets/_scrolling_content.dart +++ b/lib/ui/screens/editorial/widgets/_scrolling_content.dart @@ -89,50 +89,57 @@ class _ScrollingContent extends StatelessWidget { sliver: SliverPadding( padding: EdgeInsets.symmetric(vertical: $styles.insets.md), sliver: SliverList( - delegate: SliverChildListDelegate([ - ..._contentSection([ - Center(child: buildHiddenCollectible(slot: 0)), + delegate: SliverChildListDelegate.fixed([ + Center( + child: SizedBox( + width: $styles.sizes.maxContentWidth1, + child: Column(children: [ + ..._contentSection([ + Center(child: buildHiddenCollectible(slot: 0)), - /// History 1 - buildDropCapText(data.historyInfo1), + /// History 1 + buildDropCapText(data.historyInfo1), - /// Quote1 - _CollapsingPullQuoteImage(data: data, scrollPos: scrollPos), - Center(child: buildHiddenCollectible(slot: 1)), + /// Quote1 + _CollapsingPullQuoteImage(data: data, scrollPos: scrollPos), + Center(child: buildHiddenCollectible(slot: 1)), - /// Callout1 - _Callout(text: data.callout1), + /// Callout1 + _Callout(text: data.callout1), - /// History 2 - buildText(data.historyInfo2), - _SectionDivider(scrollPos, sectionNotifier, index: 1), + /// History 2 + buildText(data.historyInfo2), + _SectionDivider(scrollPos, sectionNotifier, index: 1), - /// Construction 1 - buildDropCapText(data.constructionInfo1), - Center(child: buildHiddenCollectible(slot: 2)), - ]), - Gap($styles.insets.md), - _YouTubeThumbnail(id: data.videoId, caption: data.videoCaption), - Gap($styles.insets.md), - ..._contentSection([ - /// Callout2 - Gap($styles.insets.xs), - _Callout(text: data.callout2), + /// Construction 1 + buildDropCapText(data.constructionInfo1), + Center(child: buildHiddenCollectible(slot: 2)), + ]), + Gap($styles.insets.md), + _YouTubeThumbnail(id: data.videoId, caption: data.videoCaption), + Gap($styles.insets.md), + ..._contentSection([ + /// Callout2 + Gap($styles.insets.xs), + _Callout(text: data.callout2), - /// Construction 2 - buildText(data.constructionInfo2), - _SlidingImageStack(scrollPos: scrollPos, type: data.type), - _SectionDivider(scrollPos, sectionNotifier, index: 2), + /// Construction 2 + buildText(data.constructionInfo2), + _SlidingImageStack(scrollPos: scrollPos, type: data.type), + _SectionDivider(scrollPos, sectionNotifier, index: 2), - /// Location - buildDropCapText(data.locationInfo1), - _LargeSimpleQuote(text: data.pullQuote2, author: data.pullQuote2Author), - buildText(data.locationInfo2), - ]), - Gap($styles.insets.md), - _MapsThumbnail(data, height: 200), - Gap($styles.insets.md), - ..._contentSection([Center(child: buildHiddenCollectible(slot: 3))]), + /// Location + buildDropCapText(data.locationInfo1), + _LargeSimpleQuote(text: data.pullQuote2, author: data.pullQuote2Author), + buildText(data.locationInfo2), + ]), + Gap($styles.insets.md), + _MapsThumbnail(data, height: 200), + Gap($styles.insets.md), + ..._contentSection([Center(child: buildHiddenCollectible(slot: 3))]), + ]), + ), + ), ]), ), ), @@ -221,6 +228,7 @@ class _MapsThumbnailState extends State<_MapsThumbnail> { @override Widget build(BuildContext context) { void handlePressed() => context.push(ScreenPaths.maps(widget.data.type)); + if (PlatformInfo.isDesktop) return Placeholder(); return MergeSemantics( child: Column( children: [ diff --git a/lib/ui/screens/editorial/widgets/_title_text.dart b/lib/ui/screens/editorial/widgets/_title_text.dart index 7dd45066..59f5e050 100644 --- a/lib/ui/screens/editorial/widgets/_title_text.dart +++ b/lib/ui/screens/editorial/widgets/_title_text.dart @@ -11,83 +11,88 @@ class _TitleText extends StatelessWidget { child: DefaultTextColor( color: $styles.colors.offWhite, child: StaticTextScale( - child: Column( - children: [ - Gap($styles.insets.md), - Gap(30), - - /// Sub-title row - SeparatedRow( - padding: EdgeInsets.symmetric(horizontal: $styles.insets.sm), - separatorBuilder: () => Gap($styles.insets.sm), + child: Center( + child: SizedBox( + width: $styles.sizes.maxContentWidth1, + child: Column( children: [ - Expanded( - child: Divider( - color: data.type.fgColor, - ).animate().scale(curve: Curves.easeOut, delay: 500.ms), + Gap($styles.insets.md), + Gap(30), + + /// Sub-title row + SeparatedRow( + padding: EdgeInsets.symmetric(horizontal: $styles.insets.sm), + separatorBuilder: () => Gap($styles.insets.sm), + children: [ + Expanded( + child: Divider( + color: data.type.fgColor, + ).animate().scale(curve: Curves.easeOut, delay: 500.ms), + ), + Semantics( + header: true, + sortKey: OrdinalSortKey(1), + child: Text( + data.subTitle.toUpperCase(), + style: $styles.text.title2, + ).animate().fade(delay: 100.ms), + ), + Expanded( + child: Divider( + color: data.type.fgColor, + ).animate().scale(curve: Curves.easeOut, delay: 500.ms), + ), + ], ), + Gap($styles.insets.md), + + /// Wonder title text Semantics( - header: true, - sortKey: OrdinalSortKey(1), - child: Text( - data.subTitle.toUpperCase(), - style: $styles.text.title2, - ).animate().fade(delay: 100.ms), + sortKey: OrdinalSortKey(0), + child: ListenableBuilder( + listenable: scroller, + builder: (_, __) { + final yPos = ContextUtils.getGlobalPos(context)?.dy ?? 0; + bool enableHero = yPos > -100; + return WonderTitleText(data, enableHero: enableHero); + }), ), - Expanded( - child: Divider( - color: data.type.fgColor, - ).animate().scale(curve: Curves.easeOut, delay: 500.ms), + Gap($styles.insets.xs), + + /// Region + Text( + data.regionTitle.toUpperCase(), + style: $styles.text.title1, + textAlign: TextAlign.center, ), - ], - ), - Gap($styles.insets.md), + Gap($styles.insets.md), - /// Wonder title text - Semantics( - sortKey: OrdinalSortKey(0), - child: ListenableBuilder( - listenable: scroller, - builder: (_, __) { - final yPos = ContextUtils.getGlobalPos(context)?.dy ?? 0; - bool enableHero = yPos > -100; - return WonderTitleText(data, enableHero: enableHero); - }), - ), - Gap($styles.insets.xs), - - /// Region - Text( - data.regionTitle.toUpperCase(), - style: $styles.text.title1, - textAlign: TextAlign.center, - ), - Gap($styles.insets.md), - - /// Compass divider - ExcludeSemantics( - child: Padding( - padding: EdgeInsets.symmetric(horizontal: $styles.insets.md), - child: ListenableBuilder( - listenable: scroller, - builder: (_, __) => CompassDivider( - isExpanded: scroller.position.pixels <= 0, - linesColor: data.type.fgColor, - compassColor: $styles.colors.offWhite, + /// Compass divider + ExcludeSemantics( + child: Padding( + padding: EdgeInsets.symmetric(horizontal: $styles.insets.md), + child: ListenableBuilder( + listenable: scroller, + builder: (_, __) => CompassDivider( + isExpanded: scroller.position.pixels <= 0, + linesColor: data.type.fgColor, + compassColor: $styles.colors.offWhite, + ), + ), ), ), - ), - ), - Gap($styles.insets.sm), + Gap($styles.insets.sm), - /// Date - Text( - $strings.titleLabelDate(StringUtils.formatYr(data.startYr), StringUtils.formatYr(data.endYr)), - style: $styles.text.h4, - textAlign: TextAlign.center, + /// Date + Text( + $strings.titleLabelDate(StringUtils.formatYr(data.startYr), StringUtils.formatYr(data.endYr)), + style: $styles.text.h4, + textAlign: TextAlign.center, + ), + Gap($styles.insets.sm), + ], ), - Gap($styles.insets.sm), - ], + ), ), ), ), 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 ddb01003..08ae5636 100644 --- a/lib/ui/screens/wonder_details/wonder_details_tab_menu.dart +++ b/lib/ui/screens/wonder_details/wonder_details_tab_menu.dart @@ -125,7 +125,7 @@ class _TabBtn extends StatelessWidget { final iconImgPath = '${ImagePaths.common}/tab-$iconImg${selected ? '-active' : ''}.png'; String tabLabel = localizations.tabLabel(tabIndex: index + 1, tabCount: tabController.length); tabLabel = '$label: $tabLabel'; - final double btnWidth = (context.widthPx / 6).clamp(80, 120); + final double btnWidth = (context.widthPx / 6).clamp(70, 120); return MergeSemantics( child: Semantics( selected: selected, @@ -136,25 +136,8 @@ class _TabBtn extends StatelessWidget { onPressed: () => tabController.index = index, semanticLabel: label, minimumSize: Size(btnWidth, 0), - child: Stack( - children: [ - /// Image icon - Image.asset(iconImgPath, height: 32, width: 32, color: selected ? null : color), - // if (selected) - // Positioned.fill( - // child: BottomCenter( - // child: Transform.translate( - // offset: Offset(0, $styles.insets.xxs), - // child: Animate().custom( - // curve: Curves.easeOutCubic, - // end: 24, - // builder: (_, v, __) => Container(height: 3, width: v, color: $styles.colors.accent1), - // ), - // ), - // ), - // ), - ], - ), + // Image icon + child: Image.asset(iconImgPath, height: 32, width: 32, color: selected ? null : color), ), ), ), diff --git a/pubspec.lock b/pubspec.lock index 7348aa21..808dbd67 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1149,10 +1149,10 @@ packages: dependency: transitive description: name: string_scanner - sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + sha256: "862015c5db1f3f3c4ea3b94dc2490363a84262994b88902315ed74be1155612f" url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.1.1" sync_http: dependency: transitive description: @@ -1173,10 +1173,10 @@ packages: dependency: transitive description: name: test_api - sha256: ad540f65f92caa91bf21dfc8ffb8c589d6e4dc0c2267818b4cc2792857706206 + sha256: c9aba3b3dbfe8878845dfab5fa096eb8de7b62231baeeb1cea8e3ee81ca8c6d8 url: "https://pub.dev" source: hosted - version: "0.4.16" + version: "0.4.15" timing: dependency: transitive description: