mirror of
https://github.com/flutter/flutter
synced 2024-08-27 12:00:58 +00:00
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:
parent
91d751f8cd
commit
90776462e9
|
@ -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);
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in a new issue