Allow transparent barrierColor in showDialog methods (#61516)

`showDialog()` and `showGeneralDialog()` were allowing transparent
colors but then triggering an assertion down the stack while building
the modal barrier. The assertion existed to keep from animating from
transparent to transparent, but there's no need for the assertion,
since we can just treat the transparent case as the same as the null
case -- no animation necessary.
This commit is contained in:
Todd Volkert 2020-07-16 09:43:47 -07:00 committed by GitHub
parent 681395e888
commit e2cdc9f981
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 71 additions and 1 deletions

View file

@ -1435,7 +1435,7 @@ abstract class ModalRoute<T> extends TransitionRoute<T> with LocalHistoryRoute<T
OverlayEntry _modalBarrier;
Widget _buildModalBarrier(BuildContext context) {
Widget barrier;
if (barrierColor != null && !offstage) { // changedInternalState is called if barrierColor or offstage updates
if (barrierColor != null && barrierColor.alpha != 0 && !offstage) { // changedInternalState is called if barrierColor or offstage updates
assert(barrierColor != _kTransparent);
final Animation<Color> color = animation.drive(
ColorTween(

View file

@ -966,6 +966,76 @@ void main() {
expect(secondaryAnimationOfRouteOne.value, primaryAnimationOfRouteTwo.value);
});
testWidgets('showGeneralDialog handles transparent barrier color', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
home: Builder(
builder: (BuildContext context) {
return RaisedButton(
onPressed: () {
showGeneralDialog<void>(
context: context,
barrierDismissible: true,
barrierLabel: 'barrier_label',
barrierColor: const Color(0x00000000),
transitionDuration: Duration.zero,
pageBuilder: (BuildContext innerContext, _, __) {
return const SizedBox();
},
);
},
child: const Text('Show Dialog'),
);
},
),
));
// Open the dialog.
await tester.tap(find.byType(RaisedButton));
await tester.pump();
expect(find.byType(ModalBarrier), findsNWidgets(2));
// Close the dialog.
await tester.tapAt(Offset.zero);
await tester.pump();
expect(find.byType(ModalBarrier), findsNWidgets(1));
});
testWidgets('showGeneralDialog adds non-dismissable barrier when barrierDismissable is false', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
home: Builder(
builder: (BuildContext context) {
return RaisedButton(
onPressed: () {
showGeneralDialog<void>(
context: context,
barrierDismissible: false,
transitionDuration: Duration.zero,
pageBuilder: (BuildContext innerContext, _, __) {
return const SizedBox();
},
);
},
child: const Text('Show Dialog'),
);
},
),
));
// Open the dialog.
await tester.tap(find.byType(RaisedButton));
await tester.pump();
expect(find.byType(ModalBarrier), findsNWidgets(2));
final ModalBarrier barrier = find.byType(ModalBarrier).evaluate().last.widget as ModalBarrier;
expect(barrier.dismissible, isFalse);
// Close the dialog.
final StatefulElement navigatorElement = find.byType(Navigator).evaluate().last as StatefulElement;
final NavigatorState navigatorState = navigatorElement.state as NavigatorState;
navigatorState.pop();
await tester.pumpAndSettle();
expect(find.byType(ModalBarrier), findsNWidgets(1));
});
testWidgets('showGeneralDialog uses root navigator by default', (WidgetTester tester) async {
final DialogObserver rootObserver = DialogObserver();
final DialogObserver nestedObserver = DialogObserver();