Skip to content

Commit

Permalink
Fix floating SnackBar is not centered when RTL and Material 2 (#147861)
Browse files Browse the repository at this point in the history
## Description

This PR fixes floating `SnackBar` positioning when the text direction is RTL and the theme uses Material 2.

In flutter/flutter#140215, I fixed the `SnackBar` position for M3/RTL, but while doing so I broke the positioning for M2/RTL... Unfortunately, there was no existing test for this case.
The solution is to not rely on `TextDirection` to compute the `SnackBar` position: the `SnackBar` is centered in both cases so the text direction has no impact on its positioning (it had some impact in the `SnackBar` content, but this is managed correctly).

## Related Issue

Fixes flutter/flutter#147838.

## Tests

Adds 1 test.
  • Loading branch information
bleroux authored May 8, 2024
1 parent a318c79 commit 86a2613
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 10 deletions.
8 changes: 1 addition & 7 deletions packages/flutter/lib/src/material/scaffold.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1217,13 +1217,7 @@ class _ScaffoldLayout extends MultiChildLayoutDelegate {
: contentBottom;
}

double xOffset = 0.0;
if (hasCustomWidth) {
xOffset = switch (textDirection) {
TextDirection.rtl => (snackBarWidth! - size.width) / 2,
TextDirection.ltr => (size.width - snackBarWidth!) / 2,
};
}
final double xOffset = hasCustomWidth ? (size.width - snackBarWidth!) / 2 : 0.0;
positionChild(_ScaffoldSlot.snackBar, Offset(xOffset, snackBarYOffsetBase - snackBarSize.height));

assert((){
Expand Down
2 changes: 1 addition & 1 deletion packages/flutter/lib/src/material/snack_bar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -819,7 +819,7 @@ class _SnackBarState extends State<SnackBar> {
animation: heightM3Animation,
builder: (BuildContext context, Widget? child) {
return Align(
alignment: AlignmentDirectional.bottomStart,
alignment: Alignment.bottomLeft,
heightFactor: heightM3Animation.value,
child: child,
);
Expand Down
48 changes: 46 additions & 2 deletions packages/flutter/test/material/snack_bar_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2601,7 +2601,7 @@ void main() {
},
);

testWidgets('Floating snackbar with custom width is centered when text direction is rtl', (WidgetTester tester) async {
testWidgets('Material3 - Floating snackbar with custom width is centered when text direction is rtl', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/140125.
const double customWidth = 400.0;
await tester.pumpWidget(
Expand Down Expand Up @@ -2631,7 +2631,51 @@ void main() {
);

await tester.tap(find.text('X'));
await tester.pump(); // start animation
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);
final Offset snackBarBottomRight = tester.getBottomRight(materialFinder);
expect(snackBarBottomLeft.dx, (800 - customWidth) / 2); // Device width is 800.
expect(snackBarBottomRight.dx, (800 + customWidth) / 2); // Device width is 800.
});

testWidgets('Material2 - Floating snackbar with custom width is centered when text direction is rtl', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/147838.
const double customWidth = 400.0;
await tester.pumpWidget(
MaterialApp(
theme: ThemeData(useMaterial3: false),
home: Directionality(
textDirection: TextDirection.rtl,
child: Scaffold(
body: Builder(
builder: (BuildContext context) {
return GestureDetector(
onTap: () {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
behavior: SnackBarBehavior.floating,
width: customWidth,
content: Text('Feeling super snackish'),
),
);
},
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(
Expand Down

0 comments on commit 86a2613

Please sign in to comment.