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].*
This commit is contained in:
parent
e90f980f40
commit
c3cd01661c
@ -283,6 +283,7 @@ class SnackBar extends StatefulWidget {
|
|||||||
this.padding,
|
this.padding,
|
||||||
this.width,
|
this.width,
|
||||||
this.shape,
|
this.shape,
|
||||||
|
this.hitTestBehavior,
|
||||||
this.behavior,
|
this.behavior,
|
||||||
this.action,
|
this.action,
|
||||||
this.actionOverflowThreshold,
|
this.actionOverflowThreshold,
|
||||||
@ -331,6 +332,8 @@ class SnackBar extends StatefulWidget {
|
|||||||
/// If this property is null, then [SnackBarThemeData.insetPadding] of
|
/// If this property is null, then [SnackBarThemeData.insetPadding] of
|
||||||
/// [ThemeData.snackBarTheme] is used. If that is also null, then the default is
|
/// [ThemeData.snackBarTheme] is used. If that is also null, then the default is
|
||||||
/// `EdgeInsets.fromLTRB(15.0, 5.0, 15.0, 10.0)`.
|
/// `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;
|
final EdgeInsetsGeometry? margin;
|
||||||
|
|
||||||
/// The amount of padding to apply to the snack bar's content and optional
|
/// 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.
|
/// circular corner radius of 4.0.
|
||||||
final ShapeBorder? shape;
|
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.
|
/// This defines the behavior and location of the snack bar.
|
||||||
///
|
///
|
||||||
/// Defines where a [SnackBar] should appear within a [Scaffold] and how its
|
/// Defines where a [SnackBar] should appear within a [Scaffold] and how its
|
||||||
@ -489,6 +499,7 @@ class SnackBar extends StatefulWidget {
|
|||||||
padding: padding,
|
padding: padding,
|
||||||
width: width,
|
width: width,
|
||||||
shape: shape,
|
shape: shape,
|
||||||
|
hitTestBehavior: hitTestBehavior,
|
||||||
behavior: behavior,
|
behavior: behavior,
|
||||||
action: action,
|
action: action,
|
||||||
actionOverflowThreshold: actionOverflowThreshold,
|
actionOverflowThreshold: actionOverflowThreshold,
|
||||||
@ -776,6 +787,7 @@ class _SnackBarState extends State<SnackBar> {
|
|||||||
key: const Key('dismissible'),
|
key: const Key('dismissible'),
|
||||||
direction: widget.dismissDirection,
|
direction: widget.dismissDirection,
|
||||||
resizeDuration: null,
|
resizeDuration: null,
|
||||||
|
behavior: widget.hitTestBehavior ?? (widget.margin != null ? HitTestBehavior.deferToChild : HitTestBehavior.opaque),
|
||||||
onDismissed: (DismissDirection direction) {
|
onDismissed: (DismissDirection direction) {
|
||||||
ScaffoldMessenger.of(context).removeCurrentSnackBar(reason: SnackBarClosedReason.swipe);
|
ScaffoldMessenger.of(context).removeCurrentSnackBar(reason: SnackBarClosedReason.swipe);
|
||||||
},
|
},
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
@Tags(<String>['reduced-test-set'])
|
@Tags(<String>['reduced-test-set'])
|
||||||
library;
|
library;
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
import 'dart:ui';
|
import 'dart:ui';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@ -2915,6 +2916,175 @@ testWidgets('SnackBarAction backgroundColor works as a Color', (WidgetTester tes
|
|||||||
|
|
||||||
expect(material.clipBehavior, Clip.antiAlias);
|
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".
|
/// Start test for "SnackBar dismiss test".
|
||||||
|
Loading…
x
Reference in New Issue
Block a user