Unverified Commit 66cd09dd authored by Taha Tesser's avatar Taha Tesser Committed by GitHub

Update `PopupRoute` docs and add an example (#106948)

parent a8d04792
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flutter code sample for PopupRoute
import 'package:flutter/material.dart';
void main() => runApp(const PopupRouteApp());
class PopupRouteApp extends StatelessWidget {
const PopupRouteApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: PopupRouteExample(),
);
}
}
class PopupRouteExample extends StatelessWidget {
const PopupRouteExample({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: OutlinedButton(
onPressed: () {
/// This shows a dismissible dialog.
Navigator.of(context).push(DismissibleDialog<void>());
},
child: const Text('Open DismissibleDialog'),
),
),
);
}
}
class DismissibleDialog<T> extends PopupRoute<T> {
@override
Color? get barrierColor => Colors.black.withAlpha(0x50);
/// This allows the popup to be dismissed by tapping the scrim or by
/// pressing escape key on the keyboard.
@override
bool get barrierDismissible => true;
@override
String? get barrierLabel => 'Dismissible Dialog';
@override
Duration get transitionDuration => const Duration(milliseconds: 300);
@override
Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
return Center(
/// Provide DefaultTextStyle to ensure that the dialog's text style matches
/// the rest of the text in the app.
child: DefaultTextStyle(
style: Theme.of(context).textTheme.bodyMedium!,
/// `UnconstrainedBox` is used to make the dialog size itself
/// to fit to the size of the content.
child: UnconstrainedBox(
child: Container(
padding: const EdgeInsets.all(20.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.white,
),
child: Column(
children: <Widget>[
Text('Dismissible Dialog', style: Theme.of(context).textTheme.headlineSmall),
const SizedBox(height: 20),
const Text('Tap in the scrim or press escape key to dismiss.'),
],
),
),
),
),
);
}
}
......@@ -6,25 +6,22 @@
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
void main() => runApp(const GeneralDialogApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
static const String _title = 'Flutter Code Sample';
class GeneralDialogApp extends StatelessWidget {
const GeneralDialogApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
restorationScopeId: 'app',
title: _title,
home: MyStatelessWidget(),
home: GeneralDialogExample(),
);
}
}
class MyStatelessWidget extends StatelessWidget {
const MyStatelessWidget({super.key});
class GeneralDialogExample extends StatelessWidget {
const GeneralDialogExample({super.key});
@override
Widget build(BuildContext context) {
......@@ -32,6 +29,7 @@ class MyStatelessWidget extends StatelessWidget {
body: Center(
child: OutlinedButton(
onPressed: () {
/// This shows an alert dialog.
Navigator.of(context).restorablePush(_dialogBuilder);
},
child: const Text('Open Dialog'),
......
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_api_samples/widgets/routes/popup_route.0.dart' as example;
import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets('Dismiss dialog with tap on the scrim and escape key', (WidgetTester tester) async {
const String dialogText = 'Tap in the scrim or press escape key to dismiss.';
await tester.pumpWidget(
const example.PopupRouteApp(),
);
expect(find.text(dialogText), findsNothing);
// Tap on the button to show the dialog.
await tester.tap(find.byType(OutlinedButton));
await tester.pumpAndSettle();
expect(find.text(dialogText), findsOneWidget);
// Try to dismiss the dialog with a tap on the scrim.
await tester.tapAt(const Offset(10.0, 10.0));
await tester.pumpAndSettle();
expect(find.text(dialogText), findsNothing);
// Open the dialog again.
await tester.tap(find.byType(OutlinedButton));
await tester.pumpAndSettle();
expect(find.text(dialogText), findsOneWidget);
// Try to dismiss the dialog with the escape key.
await tester.sendKeyEvent(LogicalKeyboardKey.escape);
await tester.pumpAndSettle();
expect(find.text(dialogText), findsNothing);
});
}
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/material.dart';
import 'package:flutter_api_samples/widgets/routes/show_general_dialog.0.dart' as example;
import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets('Open and dismiss general dialog', (WidgetTester tester) async {
const String dialogText = 'Alert!';
await tester.pumpWidget(
const example.GeneralDialogApp(),
);
expect(find.text(dialogText), findsNothing);
// Tap on the button to show the dialog.
await tester.tap(find.byType(OutlinedButton));
await tester.pumpAndSettle();
expect(find.text(dialogText), findsOneWidget);
// Try to dismiss the dialog with a tap on the scrim.
await tester.tapAt(const Offset(10.0, 10.0));
await tester.pumpAndSettle();
expect(find.text(dialogText), findsNothing);
});
}
......@@ -1210,8 +1210,10 @@ abstract class ModalRoute<T> extends TransitionRoute<T> with LocalHistoryRoute<T
/// For example, when a dialog is on the screen, the page below the dialog is
/// usually darkened by the modal barrier.
///
/// If [barrierDismissible] is true, then tapping this barrier will cause the
/// current route to be popped (see [Navigator.pop]) with null as the value.
/// If [barrierDismissible] is true, then tapping this barrier, pressing
/// the escape key on the keyboard, or calling route popping functions
/// such as [Navigator.pop] will cause the current route to be popped
/// with null as the value.
///
/// If [barrierDismissible] is false, then tapping the barrier has no effect.
///
......@@ -1226,6 +1228,7 @@ abstract class ModalRoute<T> extends TransitionRoute<T> with LocalHistoryRoute<T
///
/// See also:
///
/// * [Navigator.pop], which is used to dismiss the route.
/// * [barrierColor], which controls the color of the scrim for this route.
/// * [ModalBarrier], the widget that implements this feature.
/// {@endtemplate}
......@@ -1691,6 +1694,19 @@ abstract class ModalRoute<T> extends TransitionRoute<T> with LocalHistoryRoute<T
}
/// A modal route that overlays a widget over the current route.
///
/// {@macro flutter.widgets.ModalRoute.barrierDismissible}
///
/// {@tool dartpad}
/// This example shows how to create a dialog box that is dismissible.
///
/// ** See code in examples/api/lib/widgets/routes/popup_route.0.dart **
/// {@end-tool}
///
/// See also:
///
/// * [ModalRoute], which is the base class for this class.
/// * [Navigator.pop], which is used to dismiss the route.
abstract class PopupRoute<T> extends ModalRoute<T> {
/// Initializes the [PopupRoute].
PopupRoute({
......
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