Fix bottom app bar height and end-contained fab location (#123746)

Fix bottom app bar height and end-contained fab location
This commit is contained in:
Qun Cheng 2023-03-30 12:50:00 -07:00 committed by GitHub
parent 91d751f8cd
commit 90776462e9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 56 additions and 13 deletions

View file

@ -194,9 +194,12 @@ class _BottomAppBarState extends State<BottomAppBar> {
final Color effectiveColor = isMaterial3 ? color : ElevationOverlay.applyOverlay(context, color, elevation);
final Color shadowColor = widget.shadowColor ?? babTheme.shadowColor ?? defaults.shadowColor!;
final Widget child = Padding(
padding: widget.padding ?? babTheme.padding ?? (isMaterial3 ? const EdgeInsets.symmetric(vertical: 12.0, horizontal: 16.0) : EdgeInsets.zero),
child: widget.child,
final Widget child = SizedBox(
height: height,
child: Padding(
padding: widget.padding ?? babTheme.padding ?? (isMaterial3 ? const EdgeInsets.symmetric(vertical: 12.0, horizontal: 16.0) : EdgeInsets.zero),
child: widget.child,
),
);
final Material material = Material(
@ -209,16 +212,14 @@ class _BottomAppBarState extends State<BottomAppBar> {
child: SafeArea(child: child),
);
final PhysicalShape physicalShape = PhysicalShape(
return PhysicalShape(
clipper: clipper,
elevation: elevation,
shadowColor: shadowColor,
color: effectiveColor,
clipBehavior: widget.clipBehavior,
child: material,
);
return SizedBox(height: height, child: physicalShape);
);
}
}

View file

@ -630,20 +630,24 @@ mixin FabContainedOffsetY on StandardFabLocation {
final double contentMargin = scaffoldGeometry.scaffoldSize.height - contentBottom;
final double bottomViewPadding = scaffoldGeometry.minViewPadding.bottom;
final double fabHeight = scaffoldGeometry.floatingActionButtonSize.height;
final double bottomMinInset = scaffoldGeometry.minInsets.bottom;
double safeMargin = 0.0;
if (contentMargin > bottomMinInset + fabHeight / 2.0) {
// If contentMargin is higher than bottomMinInset enough to display the
double safeMargin;
if (contentMargin > bottomViewPadding + fabHeight) {
// If contentMargin is higher than bottomViewPadding enough to display the
// FAB without clipping, don't provide a margin
safeMargin = 0.0;
} else {
safeMargin = bottomViewPadding;
}
final double fabY = contentBottom - fabHeight / 2.0 - safeMargin;
// This is to compute the distance between the content bottom to the top edge
// of the floating action button. This can be negative if content margin is
// too small.
final double contentBottomToFabTop = (contentMargin - bottomViewPadding - fabHeight) / 2.0;
final double fabY = contentBottom + contentBottomToFabTop;
final double maxFabY = scaffoldGeometry.scaffoldSize.height - fabHeight - safeMargin;
return math.min(maxFabY, fabY + contentMargin / 2);
return math.min(maxFabY, fabY);
}
}

View file

@ -616,6 +616,44 @@ void main() {
physicalShape = tester.widget(find.byType(PhysicalShape).at(0));
expect(physicalShape.clipper.toString(), 'ShapeBorderClipper');
});
testWidgets('BottomAppBar adds bottom padding to height', (WidgetTester tester) async {
const double bottomPadding = 35.0;
await tester.pumpWidget(
MediaQuery(
data: const MediaQueryData(
padding: EdgeInsets.only(bottom: bottomPadding),
viewPadding: EdgeInsets.only(bottom: bottomPadding),
),
child: MaterialApp(
theme: ThemeData(useMaterial3: true),
home: Scaffold(
floatingActionButtonLocation: FloatingActionButtonLocation.endContained,
floatingActionButton: FloatingActionButton(onPressed: () { }),
bottomNavigationBar: BottomAppBar(
child: IconButton(
icon: const Icon(Icons.search),
onPressed: () {},
),
),
),
),
)
);
final Rect bottomAppBar = tester.getRect(find.byType(BottomAppBar));
final Rect iconButton = tester.getRect(find.widgetWithIcon(IconButton, Icons.search));
final Rect fab = tester.getRect(find.byType(FloatingActionButton));
// The height of the bottom app bar should be its height(default is 80.0) + bottom safe area height.
expect(bottomAppBar.height, 80.0 + bottomPadding);
// The vertical position of the icon button and fab should be center of the area excluding the bottom padding.
final double barCenter = bottomAppBar.topLeft.dy + (bottomAppBar.height - bottomPadding) / 2;
expect(iconButton.center.dy, barCenter);
expect(fab.center.dy, barCenter);
});
}
// The bottom app bar clip path computation is only available at paint time.