Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion packages/flutter/lib/src/material/scaffold.dart
Original file line number Diff line number Diff line change
Expand Up @@ -578,7 +578,15 @@ class _ScaffoldLayout extends MultiChildLayoutDelegate {
if (floatingActionButtonRect.size != Size.zero && isSnackBarFloating) {
snackBarYOffsetBase = floatingActionButtonRect.top;
} else {
snackBarYOffsetBase = contentBottom;
// SnackBarBehavior.fixed applies a SafeArea automatically.
// SnackBarBehavior.floating does not since the positioning is affected
// if there is a FloatingActionButton (see condition above). If there is
// no FAB, make sure we account for safe space when the SnackBar is
// floating.
final double safeYOffsetBase = size.height - minViewPadding.bottom;
snackBarYOffsetBase = isSnackBarFloating
? math.min(contentBottom, safeYOffsetBase)
: contentBottom;
}

final double xOffset = hasCustomWidth ? (size.width - snackBarWidth) / 2 : 0.0;
Expand Down
47 changes: 47 additions & 0 deletions packages/flutter/test/material/snack_bar_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,53 @@ void main() {
expect(snackBarBottomRight.dx, 800 - padding); // Device width is 800.
});

testWidgets('SnackbarBehavior.floating is positioned within safe area', (WidgetTester tester) async {
const double viewPadding = 50.0;
const double floatingSnackBarDefaultBottomMargin = 10.0;
await tester.pumpWidget(
MaterialApp(
home: MediaQuery(
data: const MediaQueryData(
// Simulate non-safe area.
viewPadding: EdgeInsets.only(bottom: viewPadding),
),
child: Scaffold(
body: Builder(
builder: (BuildContext context) {
return GestureDetector(
onTap: () {
Scaffold.of(context).showSnackBar(
const SnackBar(
content: Text('I am a snack bar.'),
behavior: SnackBarBehavior.floating,
),
);
},
child: const Text('X'),
);
}
),
),
),
),
);

await tester.tap(find.text('X'));
await tester.pump(); // Start animation
await tester.pump(const Duration(milliseconds: 750));

final Finder materialFinder = find.descendant(
of: find.byType(SnackBar),
matching: find.byType(Material),
);
final Offset snackBarBottomLeft = tester.getBottomLeft(materialFinder);
expect(
snackBarBottomLeft.dy,
// Device height is 600.
600 - viewPadding - floatingSnackBarDefaultBottomMargin,
);
});

testWidgets('Snackbar padding can be customized', (WidgetTester tester) async {
const double padding = 20.0;
await tester.pumpWidget(
Expand Down