Unverified Commit 49adef67 authored by Shi-Hao Hong's avatar Shi-Hao Hong Committed by GitHub

[State Restoration] Code sample templates, migrate existing code samples (#78757)

* Create state restoration templates, 

* Update existing state restoration samples to use the new templates

* Add to README, decided to require stateful widgets to include RestorationMixin
parent 7a88eb97
...@@ -65,7 +65,7 @@ follows: ...@@ -65,7 +65,7 @@ follows:
This is a simple template for which you provide everything. It has no code of This is a simple template for which you provide everything. It has no code of
its own, just the sections for `imports`, `main`, and `preamble`. You must its own, just the sections for `imports`, `main`, and `preamble`. You must
provide the `main` section to have a `main()`. provide the `main` section to have a `main()`.
### WidgetsApp Templates ### WidgetsApp Templates
These templates create a `WidgetsApp` that encloses the snippet widget. These templates import These templates create a `WidgetsApp` that encloses the snippet widget. These templates import
...@@ -82,7 +82,7 @@ the widgets library. ...@@ -82,7 +82,7 @@ the widgets library.
`build()` method, and any state variables. It also has an `imports` `build()` method, and any state variables. It also has an `imports`
section to import additional packages. Please only import things that are part section to import additional packages. Please only import things that are part
of Flutter or part of default dependencies for a `flutter create` project. of Flutter or part of default dependencies for a `flutter create` project.
- [`stateful_widget_ticker`](stateful_widget_ticker.tmpl) : Identical to the - [`stateful_widget_ticker`](stateful_widget_ticker.tmpl) : Identical to the
`stateful_widget` template, with the addition of the `TickerProviderStateMixin` `stateful_widget` template, with the addition of the `TickerProviderStateMixin`
class, enabling easy generation of animated samples. class, enabling easy generation of animated samples.
...@@ -104,11 +104,18 @@ These templates follow the same conventions as the `WidgetsApp` templates above ...@@ -104,11 +104,18 @@ These templates follow the same conventions as the `WidgetsApp` templates above
`MaterialApp` instead. These templates import the material library. `MaterialApp` instead. These templates import the material library.
- [`stateful_widget_material`](stateful_widget_material.tmpl) - [`stateful_widget_material`](stateful_widget_material.tmpl)
- [`stateful_widget_material_ticker`](stateful_widget_material_ticker.tmpl) - [`stateful_widget_material_ticker`](stateful_widget_material_ticker.tmpl)
- [`stateless_widget_material`](stateless_widget_material.tmpl) - [`stateless_widget_material`](stateless_widget_material.tmpl)
- [`stateful_widget_restoration_material`](stateful_widget_restoration_material.tmpl) :
Similar to the `stateful_widget_restoration` template, but for `MaterialApp`.
- [`stateless_widget_restoration_material`](stateful_widget_restoration_material.tmpl) :
Similar to the `stateless_widget` template, but the `MaterialApp` has `restorationScopeId`
defined.
- [`stateful_widget_scaffold`](stateful_widget_scaffold.tmpl) : Adds a `Scaffold` widget as the home - [`stateful_widget_scaffold`](stateful_widget_scaffold.tmpl) : Adds a `Scaffold` widget as the home
of the enclosing `MaterialApp` to wrap the stateful widget snippet. The `Scaffold` widget contains of the enclosing `MaterialApp` to wrap the stateful widget snippet. The `Scaffold` widget contains
an `AppBar`. an `AppBar`.
...@@ -132,17 +139,24 @@ These templates follow the same conventions as the `WidgetsApp` templates above ...@@ -132,17 +139,24 @@ These templates follow the same conventions as the `WidgetsApp` templates above
These templates follow the same conventions as the `WidgetsApp` templates above but use a These templates follow the same conventions as the `WidgetsApp` templates above but use a
`CupertinoApp` instead. These templates import the Cupertino library. `CupertinoApp` instead. These templates import the Cupertino library.
- [`stateful_widget_cupertino`](stateful_widget_cupertino.tmpl) - [`stateful_widget_cupertino`](stateful_widget_cupertino.tmpl)
- [`stateful_widget_cupertino_ticker`](stateful_widget_cupertino_ticker.tmpl) - [`stateful_widget_cupertino_ticker`](stateful_widget_cupertino_ticker.tmpl)
- [`stateless_widget_cupertino`](stateless_widget_cupertino.tmpl) - [`stateless_widget_cupertino`](stateless_widget_cupertino.tmpl)
- [`stateful_widget_cupertinoPageScaffold`](stateful_widget_cupertino_page_scaffold.tmpl) : Similar to - [`stateful_widget_cupertinoPageScaffold`](stateful_widget_cupertino_page_scaffold.tmpl) : Similar to
`stateful_widget_cupertino`, except that it wraps the stateful widget with a `stateful_widget_cupertino`, except that it wraps the stateful widget with a
`CupertinoPageScaffold`. `CupertinoPageScaffold`.
- [`stateless_widget_cupertinoPageScaffold`](stateless_widget_cupertino_page_scaffold.tmpl) : Similar to - [`stateless_widget_cupertinoPageScaffold`](stateless_widget_cupertino_page_scaffold.tmpl) : Similar to
`stateless_widget_cupertino`, except that it wraps the stateless widget with a `stateless_widget_cupertino`, except that it wraps the stateless widget with a
`CupertinoPageScaffold`. `CupertinoPageScaffold`.
- [`stateless_widget_restoration_cupertino`](stateful_widget_restoration_material.tmpl) :
Similar to the `stateless_widget` template, but the `CupertinoApp` has `restorationScopeId`
defined.
- [`stateful_widget_restoration_cupertino`](stateful_widget_restoration_material.tmpl) :
Similar to the `stateful_widget_restoration` template, but for `CupertinoApp`.
/// Flutter code sample for {{element}}
{{description}}
{{code-dartImports}}
import 'package:flutter/cupertino.dart';
{{code-imports}}
void main() => runApp(const MyApp());
/// This is the main application widget.
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
static const String _title = 'Flutter Code Sample';
@override
Widget build(BuildContext context) {
return const CupertinoApp(
restorationScopeId: 'app',
title: _title,
home: MyStatefulWidget(restorationId: 'main'),
);
}
}
{{code-preamble}}
/// This is the stateful widget that the main application instantiates.
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({Key? key, this.restorationId}) : super(key: key);
final String? restorationId;
@override
_MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}
/// This is the private State class that goes with MyStatefulWidget.
/// RestorationProperty objects can be used because of RestorationMixin.
class _MyStatefulWidgetState extends State<MyStatefulWidget> with RestorationMixin {
// In this example, the restoration ID for the mixin is passed in through
// the [StatefulWidget]'s constructor.
@override
String? get restorationId => widget.restorationId;
{{code}}
}
/// Flutter code sample for {{element}}
{{description}}
{{code-dartImports}}
import 'package:flutter/material.dart';
{{code-imports}}
void main() => runApp(const MyApp());
/// This is the main application widget.
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
static const String _title = 'Flutter Code Sample';
@override
Widget build(BuildContext context) {
return const MaterialApp(
restorationScopeId: 'app',
title: _title,
home: MyStatefulWidget(restorationId: 'main'),
);
}
}
{{code-preamble}}
/// This is the stateful widget that the main application instantiates.
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({Key? key, this.restorationId}) : super(key: key);
final String? restorationId;
@override
_MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}
/// This is the private State class that goes with MyStatefulWidget.
/// RestorationProperty objects can be used because of RestorationMixin.
class _MyStatefulWidgetState extends State<MyStatefulWidget> with RestorationMixin {
// In this example, the restoration ID for the mixin is passed in through
// the [StatefulWidget]'s constructor.
@override
String? get restorationId => widget.restorationId;
{{code}}
}
/// Flutter code sample for {{element}}
{{description}}
{{code-dartImports}}
import 'package:flutter/cupertino.dart';
{{code-imports}}
void main() => runApp(const MyApp());
/// This is the main application widget.
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
static const String _title = 'Flutter Code Sample';
@override
Widget build(BuildContext context) {
return const CupertinoApp(
restorationScopeId: 'app',
title: _title,
home: MyStatelessWidget(),
);
}
}
{{code-preamble}}
/// This is the stateless widget that the main application instantiates.
class MyStatelessWidget extends StatelessWidget {
const MyStatelessWidget({Key? key}) : super(key: key);
@override
{{code}}
}
/// Flutter code sample for {{element}}
{{description}}
{{code-dartImports}}
import 'package:flutter/material.dart';
{{code-imports}}
void main() => runApp(const MyApp());
/// This is the main application widget.
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
static const String _title = 'Flutter Code Sample';
@override
Widget build(BuildContext context) {
return const MaterialApp(
restorationScopeId: 'app',
title: _title,
home: MyStatelessWidget(),
);
}
}
{{code-preamble}}
/// This is the stateless widget that the main application instantiates.
class MyStatelessWidget extends StatelessWidget {
const MyStatelessWidget({Key? key}) : super(key: key);
@override
{{code}}
}
...@@ -1127,7 +1127,7 @@ class CupertinoModalPopupRoute<T> extends PopupRoute<T> { ...@@ -1127,7 +1127,7 @@ class CupertinoModalPopupRoute<T> extends PopupRoute<T> {
/// ///
/// For more information about state restoration, see [RestorationManager]. /// For more information about state restoration, see [RestorationManager].
/// ///
/// {@tool sample --template=freeform} /// {@tool sample --template=stateless_widget_restoration_cupertino}
/// ///
/// This sample demonstrates how to create a restorable Cupertino modal route. /// This sample demonstrates how to create a restorable Cupertino modal route.
/// This is accomplished by enabling state restoration by specifying /// This is accomplished by enabling state restoration by specifying
...@@ -1136,69 +1136,44 @@ class CupertinoModalPopupRoute<T> extends PopupRoute<T> { ...@@ -1136,69 +1136,44 @@ class CupertinoModalPopupRoute<T> extends PopupRoute<T> {
/// ///
/// {@macro flutter.widgets.RestorationManager} /// {@macro flutter.widgets.RestorationManager}
/// ///
/// ```dart imports
/// import 'package:flutter/cupertino.dart';
/// ```
///
/// ```dart /// ```dart
/// void main() { /// Widget build(BuildContext context) {
/// runApp(const MyApp()); /// return CupertinoPageScaffold(
/// } /// navigationBar: const CupertinoNavigationBar(
/// /// middle: Text('Home'),
/// class MyApp extends StatelessWidget { /// ),
/// const MyApp({Key? key}) : super(key: key); /// child: Center(child: CupertinoButton(
/// /// onPressed: () {
/// @override /// Navigator.of(context).restorablePush(_modalBuilder);
/// Widget build(BuildContext context) { /// },
/// return const CupertinoApp( /// child: const Text('Open Modal'),
/// restorationScopeId: 'app', /// )),
/// home: MyHomePage(), /// );
/// );
/// }
/// } /// }
/// ///
/// class MyHomePage extends StatelessWidget { /// static Route<void> _modalBuilder(BuildContext context, Object? arguments) {
/// const MyHomePage({Key? key}) : super(key: key); /// return CupertinoModalPopupRoute<void>(
/// /// builder: (BuildContext context) {
/// static Route<void> _modalBuilder(BuildContext context, Object? arguments) { /// return CupertinoActionSheet(
/// return CupertinoModalPopupRoute<void>( /// title: const Text('Title'),
/// builder: (BuildContext context) { /// message: const Text('Message'),
/// return CupertinoActionSheet( /// actions: <CupertinoActionSheetAction>[
/// title: const Text('Title'), /// CupertinoActionSheetAction(
/// message: const Text('Message'), /// child: const Text('Action One'),
/// actions: <CupertinoActionSheetAction>[ /// onPressed: () {
/// CupertinoActionSheetAction( /// Navigator.pop(context);
/// child: const Text('Action One'), /// },
/// onPressed: () { /// ),
/// Navigator.pop(context); /// CupertinoActionSheetAction(
/// }, /// child: const Text('Action Two'),
/// ), /// onPressed: () {
/// CupertinoActionSheetAction( /// Navigator.pop(context);
/// child: const Text('Action Two'), /// },
/// onPressed: () { /// ),
/// Navigator.pop(context); /// ],
/// }, /// );
/// ), /// },
/// ], /// );
/// );
/// },
/// );
/// }
///
/// @override
/// Widget build(BuildContext context) {
/// return CupertinoPageScaffold(
/// navigationBar: const CupertinoNavigationBar(
/// middle: Text('Home'),
/// ),
/// child: Center(child: CupertinoButton(
/// onPressed: () {
/// Navigator.of(context).restorablePush(_modalBuilder);
/// },
/// child: const Text('Open Modal'),
/// )),
/// );
/// }
/// } /// }
/// ``` /// ```
/// ///
...@@ -1293,7 +1268,7 @@ Widget _buildCupertinoDialogTransitions(BuildContext context, Animation<double> ...@@ -1293,7 +1268,7 @@ Widget _buildCupertinoDialogTransitions(BuildContext context, Animation<double>
/// ///
/// For more information about state restoration, see [RestorationManager]. /// For more information about state restoration, see [RestorationManager].
/// ///
/// {@tool sample --template=freeform} /// {@tool sample --template=stateless_widget_restoration_cupertino}
/// ///
/// This sample demonstrates how to create a restorable Cupertino dialog. This is /// This sample demonstrates how to create a restorable Cupertino dialog. This is
/// accomplished by enabling state restoration by specifying /// accomplished by enabling state restoration by specifying
...@@ -1302,60 +1277,35 @@ Widget _buildCupertinoDialogTransitions(BuildContext context, Animation<double> ...@@ -1302,60 +1277,35 @@ Widget _buildCupertinoDialogTransitions(BuildContext context, Animation<double>
/// ///
/// {@macro flutter.widgets.RestorationManager} /// {@macro flutter.widgets.RestorationManager}
/// ///
/// ```dart imports
/// import 'package:flutter/cupertino.dart';
/// ```
///
/// ```dart /// ```dart
/// void main() { /// Widget build(BuildContext context) {
/// runApp(const MyApp()); /// return CupertinoPageScaffold(
/// } /// navigationBar: const CupertinoNavigationBar(
/// /// middle: Text('Home'),
/// class MyApp extends StatelessWidget { /// ),
/// const MyApp({Key? key}) : super(key: key); /// child: Center(child: CupertinoButton(
/// /// onPressed: () {
/// @override /// Navigator.of(context).restorablePush(_dialogBuilder);
/// Widget build(BuildContext context) { /// },
/// return const CupertinoApp( /// child: const Text('Open Dialog'),
/// restorationScopeId: 'app', /// )),
/// home: MyHomePage(), /// );
/// );
/// }
/// } /// }
/// ///
/// class MyHomePage extends StatelessWidget { /// static Route<Object?> _dialogBuilder(BuildContext context, Object? arguments) {
/// const MyHomePage({Key? key}) : super(key: key); /// return CupertinoDialogRoute<void>(
/// /// context: context,
/// static Route<Object?> _dialogBuilder(BuildContext context, Object? arguments) { /// builder: (BuildContext context) {
/// return CupertinoDialogRoute<void>( /// return const CupertinoAlertDialog(
/// context: context, /// title: Text('Title'),
/// builder: (BuildContext context) { /// content: Text('Content'),
/// return const CupertinoAlertDialog( /// actions: <Widget>[
/// title: Text('Title'), /// CupertinoDialogAction(child: Text('Yes')),
/// content: Text('Content'), /// CupertinoDialogAction(child: Text('No')),
/// actions: <Widget>[ /// ],
/// CupertinoDialogAction(child: Text('Yes')), /// );
/// CupertinoDialogAction(child: Text('No')), /// },
/// ], /// );
/// );
/// },
/// );
/// }
///
/// @override
/// Widget build(BuildContext context) {
/// return CupertinoPageScaffold(
/// navigationBar: const CupertinoNavigationBar(
/// middle: Text('Home'),
/// ),
/// child: Center(child: CupertinoButton(
/// onPressed: () {
/// Navigator.of(context).restorablePush(_dialogBuilder);
/// },
/// child: const Text('Open Dialog'),
/// )),
/// );
/// }
/// } /// }
/// ``` /// ```
/// ///
......
...@@ -994,7 +994,7 @@ Widget _buildMaterialDialogTransitions(BuildContext context, Animation<double> a ...@@ -994,7 +994,7 @@ Widget _buildMaterialDialogTransitions(BuildContext context, Animation<double> a
/// ///
/// For more information about state restoration, see [RestorationManager]. /// For more information about state restoration, see [RestorationManager].
/// ///
/// {@tool sample --template=freeform} /// {@tool sample --template=stateless_widget_restoration_material}
/// ///
/// This sample demonstrates how to create a restorable Material dialog. This is /// This sample demonstrates how to create a restorable Material dialog. This is
/// accomplished by enabling state restoration by specifying /// accomplished by enabling state restoration by specifying
...@@ -1003,51 +1003,25 @@ Widget _buildMaterialDialogTransitions(BuildContext context, Animation<double> a ...@@ -1003,51 +1003,25 @@ Widget _buildMaterialDialogTransitions(BuildContext context, Animation<double> a
/// ///
/// {@macro flutter.widgets.RestorationManager} /// {@macro flutter.widgets.RestorationManager}
/// ///
/// ```dart imports
/// import 'package:flutter/material.dart';
/// ```
///
/// ```dart /// ```dart
/// void main() { /// Widget build(BuildContext context) {
/// runApp(const MyApp()); /// return Scaffold(
/// } /// body: Center(
/// /// child: OutlinedButton(
/// class MyApp extends StatelessWidget { /// onPressed: () {
/// const MyApp({Key? key}) : super(key: key); /// Navigator.of(context).restorablePush(_dialogBuilder);
/// /// },
/// @override /// child: const Text('Open Dialog'),
/// Widget build(BuildContext context) { /// ),
/// return const MaterialApp( /// ),
/// restorationScopeId: 'app', /// );
/// title: 'Restorable Routes Demo',
/// home: MyHomePage(),
/// );
/// }
/// } /// }
/// ///
/// class MyHomePage extends StatelessWidget { /// static Route<Object?> _dialogBuilder(BuildContext context, Object? arguments) {
/// const MyHomePage({Key? key}) : super(key: key); /// return DialogRoute<void>(
/// /// context: context,
/// static Route<Object?> _dialogBuilder(BuildContext context, Object? arguments) { /// builder: (BuildContext context) => const AlertDialog(title: Text('Material Alert!')),
/// return DialogRoute<void>( /// );
/// context: context,
/// builder: (BuildContext context) => const AlertDialog(title: Text('Material Alert!')),
/// );
/// }
///
/// @override
/// Widget build(BuildContext context) {
/// return Scaffold(
/// body: Center(
/// child: OutlinedButton(
/// onPressed: () {
/// Navigator.of(context).restorablePush(_dialogBuilder);
/// },
/// child: const Text('Open Dialog'),
/// ),
/// ),
/// );
/// }
/// } /// }
/// ``` /// ```
/// ///
......
...@@ -1901,7 +1901,7 @@ class RawDialogRoute<T> extends PopupRoute<T> { ...@@ -1901,7 +1901,7 @@ class RawDialogRoute<T> extends PopupRoute<T> {
/// ///
/// For more information about state restoration, see [RestorationManager]. /// For more information about state restoration, see [RestorationManager].
/// ///
/// {@tool sample --template=freeform} /// {@tool sample --template=stateless_widget_restoration_material}
/// ///
/// This sample demonstrates how to create a restorable dialog. This is /// This sample demonstrates how to create a restorable dialog. This is
/// accomplished by enabling state restoration by specifying /// accomplished by enabling state restoration by specifying
...@@ -1910,55 +1910,30 @@ class RawDialogRoute<T> extends PopupRoute<T> { ...@@ -1910,55 +1910,30 @@ class RawDialogRoute<T> extends PopupRoute<T> {
/// ///
/// {@macro flutter.widgets.RestorationManager} /// {@macro flutter.widgets.RestorationManager}
/// ///
/// ```dart imports
/// import 'package:flutter/material.dart';
/// ```
///
/// ```dart /// ```dart
/// void main() { /// Widget build(BuildContext context) {
/// runApp(const MyApp()); /// return Scaffold(
/// } /// body: Center(
/// /// child: OutlinedButton(
/// class MyApp extends StatelessWidget { /// onPressed: () {
/// const MyApp({Key? key}) : super(key: key); /// Navigator.of(context).restorablePush(_dialogBuilder);
/// /// },
/// @override /// child: const Text('Open Dialog'),
/// Widget build(BuildContext context) { /// ),
/// return const MaterialApp( /// ),
/// restorationScopeId: 'app', /// );
/// home: MyHomePage(),
/// );
/// }
/// } /// }
/// ///
/// class MyHomePage extends StatelessWidget { /// static Route<Object?> _dialogBuilder(BuildContext context, Object? arguments) {
/// const MyHomePage({Key? key}) : super(key: key); /// return RawDialogRoute<void>(
/// /// pageBuilder: (
/// static Route<Object?> _dialogBuilder(BuildContext context, Object? arguments) { /// BuildContext context,
/// return RawDialogRoute<void>( /// Animation<double> animation,
/// pageBuilder: ( /// Animation<double> secondaryAnimation,
/// BuildContext context, /// ) {
/// Animation<double> animation, /// return const AlertDialog(title: Text('Alert!'));
/// Animation<double> secondaryAnimation, /// },
/// ) { /// );
/// return const AlertDialog(title: Text('Alert!'));
/// },
/// );
/// }
///
/// @override
/// Widget build(BuildContext context) {
/// return Scaffold(
/// body: Center(
/// child: OutlinedButton(
/// onPressed: () {
/// Navigator.of(context).restorablePush(_dialogBuilder);
/// },
/// child: const Text('Open Dialog'),
/// ),
/// ),
/// );
/// }
/// } /// }
/// ``` /// ```
/// ///
......
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