Unverified Commit c3cd0166 authored by lsaudon's avatar lsaudon Committed by GitHub

Tap on button behind snack bar defined by margin (#127959)

If the margin is used, set the `HitTestBehavior` to `deferToChild`. 

*List which issues are fixed by this PR. You must list at least one issue.*
#78537 
#114810 

*If you had to change anything in the [flutter/tests] repo, include a link to the migration guide as per the [breaking change policy].*
parent e90f980f
......@@ -283,6 +283,7 @@ class SnackBar extends StatefulWidget {
this.padding,
this.width,
this.shape,
this.hitTestBehavior,
this.behavior,
this.action,
this.actionOverflowThreshold,
......@@ -331,6 +332,8 @@ class SnackBar extends StatefulWidget {
/// If this property is null, then [SnackBarThemeData.insetPadding] of
/// [ThemeData.snackBarTheme] is used. If that is also null, then the default is
/// `EdgeInsets.fromLTRB(15.0, 5.0, 15.0, 10.0)`.
///
/// If this property is not null and [hitTestBehavior] is null, then [hitTestBehavior] default is [HitTestBehavior.deferToChild].
final EdgeInsetsGeometry? margin;
/// The amount of padding to apply to the snack bar's content and optional
......@@ -384,6 +387,13 @@ class SnackBar extends StatefulWidget {
/// circular corner radius of 4.0.
final ShapeBorder? shape;
/// Defines how the snack bar area, including margin, will behave during hit testing.
///
/// If this property is null and [margin] is not null, then [HitTestBehavior.deferToChild] is used by default.
///
/// Please refer to [HitTestBehavior] for a detailed explanation of every behavior.
final HitTestBehavior? hitTestBehavior;
/// This defines the behavior and location of the snack bar.
///
/// Defines where a [SnackBar] should appear within a [Scaffold] and how its
......@@ -489,6 +499,7 @@ class SnackBar extends StatefulWidget {
padding: padding,
width: width,
shape: shape,
hitTestBehavior: hitTestBehavior,
behavior: behavior,
action: action,
actionOverflowThreshold: actionOverflowThreshold,
......@@ -776,6 +787,7 @@ class _SnackBarState extends State<SnackBar> {
key: const Key('dismissible'),
direction: widget.dismissDirection,
resizeDuration: null,
behavior: widget.hitTestBehavior ?? (widget.margin != null ? HitTestBehavior.deferToChild : HitTestBehavior.opaque),
onDismissed: (DismissDirection direction) {
ScaffoldMessenger.of(context).removeCurrentSnackBar(reason: SnackBarClosedReason.swipe);
},
......
......@@ -7,6 +7,7 @@
@Tags(<String>['reduced-test-set'])
library;
import 'dart:async';
import 'dart:ui';
import 'package:flutter/material.dart';
......@@ -2915,6 +2916,175 @@ testWidgets('SnackBarAction backgroundColor works as a Color', (WidgetTester tes
expect(material.clipBehavior, Clip.antiAlias);
});
testWidgets('Tap on button behind snack bar defined by width', (WidgetTester tester) async {
tester.view.physicalSize = const Size.square(200);
tester.view.devicePixelRatio = 1;
addTearDown(tester.view.resetPhysicalSize);
addTearDown(tester.view.resetDevicePixelRatio);
const String buttonText = 'Show snackbar';
const String snackbarContent = 'Snackbar';
const String buttonText2 = 'Try press me';
final Completer<void> completer = Completer<void>();
await tester.pumpWidget(MaterialApp(
home: Scaffold(
body: Builder(
builder: (BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
ElevatedButton(
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
behavior: SnackBarBehavior.floating,
width: 100,
content: Text(snackbarContent),
),
);
},
child: const Text(buttonText),
),
ElevatedButton(
onPressed: () {
completer.complete();
},
child: const Text(buttonText2),
),
],
);
},
),
),
));
await tester.tap(find.text(buttonText));
await tester.pumpAndSettle();
expect(find.text(snackbarContent), findsOneWidget);
await tester.tapAt(tester.getTopLeft(find.text(buttonText2)));
expect(find.text(snackbarContent), findsOneWidget);
expect(completer.isCompleted, true);
});
testWidgets('Tap on button behind snack bar defined by margin', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/78537.
tester.view.physicalSize = const Size.square(200);
tester.view.devicePixelRatio = 1;
addTearDown(tester.view.resetPhysicalSize);
addTearDown(tester.view.resetDevicePixelRatio);
const String buttonText = 'Show snackbar';
const String snackbarContent = 'Snackbar';
const String buttonText2 = 'Try press me';
final Completer<void> completer = Completer<void>();
await tester.pumpWidget(MaterialApp(
home: Scaffold(
body: Builder(
builder: (BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
ElevatedButton(
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
behavior: SnackBarBehavior.floating,
margin: EdgeInsets.only(left: 100),
content: Text(snackbarContent),
),
);
},
child: const Text(buttonText),
),
ElevatedButton(
onPressed: () {
completer.complete();
},
child: const Text(buttonText2),
),
],
);
},
),
),
));
await tester.tap(find.text(buttonText));
await tester.pumpAndSettle();
expect(find.text(snackbarContent), findsOneWidget);
await tester.tapAt(tester.getTopLeft(find.text(buttonText2)));
expect(find.text(snackbarContent), findsOneWidget);
expect(completer.isCompleted, true);
});
testWidgets("Can't tap on button behind snack bar defined by margin and HitTestBehavior.opaque", (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/78537.
tester.view.physicalSize = const Size.square(200);
tester.view.devicePixelRatio = 1;
addTearDown(tester.view.resetPhysicalSize);
addTearDown(tester.view.resetDevicePixelRatio);
const String buttonText = 'Show snackbar';
const String snackbarContent = 'Snackbar';
const String buttonText2 = 'Try press me';
final Completer<void> completer = Completer<void>();
await tester.pumpWidget(MaterialApp(
home: Scaffold(
body: Builder(
builder: (BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
ElevatedButton(
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
hitTestBehavior: HitTestBehavior.opaque,
behavior: SnackBarBehavior.floating,
margin: EdgeInsets.only(left: 100),
content: Text(snackbarContent),
),
);
},
child: const Text(buttonText),
),
ElevatedButton(
onPressed: () {
completer.complete();
},
child: const Text(buttonText2),
),
],
);
},
),
),
));
await tester.tap(find.text(buttonText));
await tester.pumpAndSettle();
expect(find.text(snackbarContent), findsOneWidget);
await tester.tapAt(tester.getTopLeft(find.text(buttonText2)));
expect(find.text(snackbarContent), findsOneWidget);
expect(completer.isCompleted, false);
});
}
/// Start test for "SnackBar dismiss test".
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment