Simplify layout of tab menu, add comments

This commit is contained in:
Shawn 2023-04-27 11:21:35 -06:00
parent 863afcae4f
commit c819bcfdef

View File

@ -1,10 +1,9 @@
import 'package:wonders/common_libs.dart'; import 'package:wonders/common_libs.dart';
class WonderDetailsTabMenu extends StatelessWidget { class WonderDetailsTabMenu extends StatelessWidget {
static double bottomPadding = 0; static const double buttonInset = 12;
static double buttonInset = 12;
static const double homeBtnSize = 74; static const double homeBtnSize = 74;
static double get minTabSize => 25; static const double minTabSize = 25;
static const double maxTabSize = 100; static const double maxTabSize = 100;
const WonderDetailsTabMenu( const WonderDetailsTabMenu(
@ -24,27 +23,28 @@ class WonderDetailsTabMenu extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
Color iconColor = showBg ? $styles.colors.black : $styles.colors.white; Color iconColor = showBg ? $styles.colors.black : $styles.colors.white;
// Measure available size after subtracting the home button size and insets
final availableSize = ((isVertical ? context.heightPx : context.widthPx) - homeBtnSize - $styles.insets.md); final availableSize = ((isVertical ? context.heightPx : context.widthPx) - homeBtnSize - $styles.insets.md);
// Calculate tabBtnSize based on availableSize
final double tabBtnSize = (availableSize / 4).clamp(minTabSize, maxTabSize); final double tabBtnSize = (availableSize / 4).clamp(minTabSize, maxTabSize);
final double homeBtnBorderSize = showBg ? 6 : 2; // Figure out some extra gap, in the case that the tabBtns are wider than the homeBtn
final double gapAmt = max(0, tabBtnSize - homeBtnSize); final double gapAmt = max(0, tabBtnSize - homeBtnSize);
// Use SafeArea padding if its more than the default padding. // Store off safe areas which we will need to respect in the layout below
bottomPadding = max(context.mq.padding.bottom, $styles.insets.xs * 1.5); final double safeAreaBtm = context.mq.padding.bottom, safeAreaTop = context.mq.padding.top;
// Insets the bg from the rounded wonder icon making it appear offset. The tab btns will use the same padding.
final buttonInsetPadding = isVertical ? EdgeInsets.only(right: buttonInset) : EdgeInsets.only(top: buttonInset);
return Padding( return Padding(
padding: EdgeInsets.only( padding: isVertical ? EdgeInsets.only(top: safeAreaTop) : EdgeInsets.zero,
top: isVertical ? context.mq.viewPadding.top : buttonInset,
right: isVertical ? buttonInset : 0,
),
child: Stack( child: Stack(
children: [ children: [
/// Background, animates in and out based on `showBg` /// Background, animates in and out based on `showBg`,
/// has padding along the inside edge which makes the home-btn appear to hang over the edge.
Positioned.fill( Positioned.fill(
child: AnimatedOpacity( child: Padding(
duration: $styles.times.fast, padding: buttonInsetPadding,
opacity: showBg ? 1 : 0, child: AnimatedOpacity(
child: Padding( duration: $styles.times.fast,
padding: EdgeInsets.only(right: isVertical ? buttonInset : 0, top: isVertical ? 0 : buttonInset), opacity: showBg ? 1 : 0,
child: Container( child: Container(
decoration: BoxDecoration( decoration: BoxDecoration(
color: $styles.colors.white, color: $styles.colors.white,
@ -56,71 +56,86 @@ class WonderDetailsTabMenu extends StatelessWidget {
), ),
/// Buttons /// Buttons
/// A Stack with a row or column of tabButtons, and an illustrated homeButton sitting on top. /// A centered row / column of tabButtons w/ an wonder home button
Padding( Padding(
padding: EdgeInsets.only(left: $styles.insets.xs * 1.5, right: $styles.insets.xxs, bottom: bottomPadding), /// When in hz mode add safeArea bottom padding, vertical layout should not need it
child: Stack( padding: EdgeInsets.only(bottom: isVertical ? 0 : safeAreaBtm),
children: [ child: SizedBox(
SizedBox( width: isVertical ? null : double.infinity,
width: isVertical ? null : double.infinity, height: isVertical ? double.infinity : null,
height: isVertical ? double.infinity : null, child: FocusTraversalGroup(
child: FocusTraversalGroup( child: Flex(
child: Flex( direction: axis,
direction: axis, mainAxisAlignment: MainAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center, mainAxisSize: MainAxisSize.min,
mainAxisSize: MainAxisSize.min, children: [
children: [ /// Home btn
/// Home btn Padding(
_WonderHomeBtn( /// Small amt of padding for home-btn
size: homeBtnSize, padding: isVertical
wonderType: wonderType, ? EdgeInsets.only(left: $styles.insets.xs)
borderSize: homeBtnBorderSize, : EdgeInsets.only(bottom: $styles.insets.xs),
), child: _WonderHomeBtn(
Gap(gapAmt), size: homeBtnSize,
wonderType: wonderType,
/// Tabs borderSize: showBg ? 6 : 2,
_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,
mainAxisSize: tabBtnSize,
),
],
), ),
), Gap(gapAmt),
/// A second Row / Col holding tab buttons
/// Add the btn inset padding so they will be centered on the colored background
Padding(
padding: buttonInsetPadding,
child: Flex(
direction: axis,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
/// 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,
mainAxisSize: tabBtnSize,
),
]),
),
],
), ),
], ),
), ),
), ),
], ],
@ -185,9 +200,9 @@ class _TabBtn extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return _isVertical // return _isVertical
? SizedBox(height: mainAxisSize, width: crossBtnSize, child: Placeholder()) // ? SizedBox(height: mainAxisSize, width: crossBtnSize, child: Placeholder())
: SizedBox(height: crossBtnSize, width: mainAxisSize, child: Placeholder()); // : SizedBox(height: crossBtnSize, width: mainAxisSize, child: Placeholder());
bool selected = tabController.index == index; bool selected = tabController.index == index;
final MaterialLocalizations localizations = MaterialLocalizations.of(context); final MaterialLocalizations localizations = MaterialLocalizations.of(context);
final iconImgPath = '${ImagePaths.common}/tab-$iconImg${selected ? '-active' : ''}.png'; final iconImgPath = '${ImagePaths.common}/tab-$iconImg${selected ? '-active' : ''}.png';
@ -202,14 +217,16 @@ class _TabBtn extends StatelessWidget {
label: tabLabel, label: tabLabel,
child: ExcludeSemantics( child: ExcludeSemantics(
child: AppBtn.basic( child: AppBtn.basic(
padding: _isVertical
? EdgeInsets.zero
: EdgeInsets.only(top: $styles.insets.md + $styles.insets.xs, bottom: $styles.insets.sm),
onPressed: () => tabController.index = index, onPressed: () => tabController.index = index,
semanticLabel: label, semanticLabel: label,
minimumSize: _isVertical ? Size(crossBtnSize, mainAxisSize) : Size(mainAxisSize, crossBtnSize), minimumSize: _isVertical ? Size(crossBtnSize, mainAxisSize) : Size(mainAxisSize, crossBtnSize),
// Image icon // Image icon
child: Image.asset(iconImgPath, height: iconSize, width: iconSize, color: selected ? null : color), child: Image.asset(
iconImgPath,
height: iconSize,
width: iconSize,
color: selected ? null : color,
),
), ),
), ),
), ),