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:
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
provide the `main` section to have a `main()`.
### WidgetsApp Templates
These templates create a `WidgetsApp` that encloses the snippet widget. These templates import
......@@ -82,7 +82,7 @@ the widgets library.
`build()` method, and any state variables. It also has an `imports`
section to import additional packages. Please only import things that are part
of Flutter or part of default dependencies for a `flutter create` project.
- [`stateful_widget_ticker`](stateful_widget_ticker.tmpl) : Identical to the
`stateful_widget` template, with the addition of the `TickerProviderStateMixin`
class, enabling easy generation of animated samples.
......@@ -104,11 +104,18 @@ These templates follow the same conventions as the `WidgetsApp` templates above
`MaterialApp` instead. These templates import the material library.
- [`stateful_widget_material`](stateful_widget_material.tmpl)
- [`stateful_widget_material_ticker`](stateful_widget_material_ticker.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
of the enclosing `MaterialApp` to wrap the stateful widget snippet. The `Scaffold` widget contains
an `AppBar`.
......@@ -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
`CupertinoApp` instead. These templates import the Cupertino library.
- [`stateful_widget_cupertino`](stateful_widget_cupertino.tmpl)
- [`stateful_widget_cupertino_ticker`](stateful_widget_cupertino_ticker.tmpl)
- [`stateless_widget_cupertino`](stateless_widget_cupertino.tmpl)
- [`stateful_widget_cupertinoPageScaffold`](stateful_widget_cupertino_page_scaffold.tmpl) : Similar to
`stateful_widget_cupertino`, except that it wraps the stateful widget with a
`CupertinoPageScaffold`.
- [`stateless_widget_cupertinoPageScaffold`](stateless_widget_cupertino_page_scaffold.tmpl) : Similar to
`stateless_widget_cupertino`, except that it wraps the stateless widget with a
`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> {
///
/// 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 is accomplished by enabling state restoration by specifying
......@@ -1136,69 +1136,44 @@ class CupertinoModalPopupRoute<T> extends PopupRoute<T> {
///
/// {@macro flutter.widgets.RestorationManager}
///
/// ```dart imports
/// import 'package:flutter/cupertino.dart';
/// ```
///
/// ```dart
/// void main() {
/// runApp(const MyApp());
/// }
///
/// class MyApp extends StatelessWidget {
/// const MyApp({Key? key}) : super(key: key);
///
/// @override
/// Widget build(BuildContext context) {
/// return const CupertinoApp(
/// restorationScopeId: 'app',
/// home: MyHomePage(),
/// );
/// }
/// 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'),
/// )),
/// );
/// }
///
/// class MyHomePage extends StatelessWidget {
/// const MyHomePage({Key? key}) : super(key: key);
///
/// static Route<void> _modalBuilder(BuildContext context, Object? arguments) {
/// return CupertinoModalPopupRoute<void>(
/// builder: (BuildContext context) {
/// return CupertinoActionSheet(
/// title: const Text('Title'),
/// message: const Text('Message'),
/// actions: <CupertinoActionSheetAction>[
/// CupertinoActionSheetAction(
/// child: const Text('Action One'),
/// onPressed: () {
/// Navigator.pop(context);
/// },
/// ),
/// CupertinoActionSheetAction(
/// 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'),
/// )),
/// );
/// }
/// static Route<void> _modalBuilder(BuildContext context, Object? arguments) {
/// return CupertinoModalPopupRoute<void>(
/// builder: (BuildContext context) {
/// return CupertinoActionSheet(
/// title: const Text('Title'),
/// message: const Text('Message'),
/// actions: <CupertinoActionSheetAction>[
/// CupertinoActionSheetAction(
/// child: const Text('Action One'),
/// onPressed: () {
/// Navigator.pop(context);
/// },
/// ),
/// CupertinoActionSheetAction(
/// child: const Text('Action Two'),
/// onPressed: () {
/// Navigator.pop(context);
/// },
/// ),
/// ],
/// );
/// },
/// );
/// }
/// ```
///
......@@ -1293,7 +1268,7 @@ Widget _buildCupertinoDialogTransitions(BuildContext context, Animation<double>
///
/// 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
/// accomplished by enabling state restoration by specifying
......@@ -1302,60 +1277,35 @@ Widget _buildCupertinoDialogTransitions(BuildContext context, Animation<double>
///
/// {@macro flutter.widgets.RestorationManager}
///
/// ```dart imports
/// import 'package:flutter/cupertino.dart';
/// ```
///
/// ```dart
/// void main() {
/// runApp(const MyApp());
/// }
///
/// class MyApp extends StatelessWidget {
/// const MyApp({Key? key}) : super(key: key);
///
/// @override
/// Widget build(BuildContext context) {
/// return const CupertinoApp(
/// restorationScopeId: 'app',
/// home: MyHomePage(),
/// );
/// }
/// 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'),
/// )),
/// );
/// }
///
/// class MyHomePage extends StatelessWidget {
/// const MyHomePage({Key? key}) : super(key: key);
///
/// static Route<Object?> _dialogBuilder(BuildContext context, Object? arguments) {
/// return CupertinoDialogRoute<void>(
/// context: context,
/// builder: (BuildContext context) {
/// return const CupertinoAlertDialog(
/// title: Text('Title'),
/// content: Text('Content'),
/// 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'),
/// )),
/// );
/// }
/// static Route<Object?> _dialogBuilder(BuildContext context, Object? arguments) {
/// return CupertinoDialogRoute<void>(
/// context: context,
/// builder: (BuildContext context) {
/// return const CupertinoAlertDialog(
/// title: Text('Title'),
/// content: Text('Content'),
/// actions: <Widget>[
/// CupertinoDialogAction(child: Text('Yes')),
/// CupertinoDialogAction(child: Text('No')),
/// ],
/// );
/// },
/// );
/// }
/// ```
///
......
......@@ -994,7 +994,7 @@ Widget _buildMaterialDialogTransitions(BuildContext context, Animation<double> a
///
/// 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
/// accomplished by enabling state restoration by specifying
......@@ -1003,51 +1003,25 @@ Widget _buildMaterialDialogTransitions(BuildContext context, Animation<double> a
///
/// {@macro flutter.widgets.RestorationManager}
///
/// ```dart imports
/// import 'package:flutter/material.dart';
/// ```
///
/// ```dart
/// void main() {
/// runApp(const MyApp());
/// }
///
/// class MyApp extends StatelessWidget {
/// const MyApp({Key? key}) : super(key: key);
///
/// @override
/// Widget build(BuildContext context) {
/// return const MaterialApp(
/// restorationScopeId: 'app',
/// title: 'Restorable Routes Demo',
/// home: MyHomePage(),
/// );
/// }
/// Widget build(BuildContext context) {
/// return Scaffold(
/// body: Center(
/// child: OutlinedButton(
/// onPressed: () {
/// Navigator.of(context).restorablePush(_dialogBuilder);
/// },
/// child: const Text('Open Dialog'),
/// ),
/// ),
/// );
/// }
///
/// class MyHomePage extends StatelessWidget {
/// const MyHomePage({Key? key}) : super(key: key);
///
/// static Route<Object?> _dialogBuilder(BuildContext context, Object? arguments) {
/// 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'),
/// ),
/// ),
/// );
/// }
/// static Route<Object?> _dialogBuilder(BuildContext context, Object? arguments) {
/// return DialogRoute<void>(
/// context: context,
/// builder: (BuildContext context) => const AlertDialog(title: Text('Material Alert!')),
/// );
/// }
/// ```
///
......
......@@ -1901,7 +1901,7 @@ class RawDialogRoute<T> extends PopupRoute<T> {
///
/// 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
/// accomplished by enabling state restoration by specifying
......@@ -1910,55 +1910,30 @@ class RawDialogRoute<T> extends PopupRoute<T> {
///
/// {@macro flutter.widgets.RestorationManager}
///
/// ```dart imports
/// import 'package:flutter/material.dart';
/// ```
///
/// ```dart
/// void main() {
/// runApp(const MyApp());
/// }
///
/// class MyApp extends StatelessWidget {
/// const MyApp({Key? key}) : super(key: key);
///
/// @override
/// Widget build(BuildContext context) {
/// return const MaterialApp(
/// restorationScopeId: 'app',
/// home: MyHomePage(),
/// );
/// }
/// Widget build(BuildContext context) {
/// return Scaffold(
/// body: Center(
/// child: OutlinedButton(
/// onPressed: () {
/// Navigator.of(context).restorablePush(_dialogBuilder);
/// },
/// child: const Text('Open Dialog'),
/// ),
/// ),
/// );
/// }
///
/// class MyHomePage extends StatelessWidget {
/// const MyHomePage({Key? key}) : super(key: key);
///
/// static Route<Object?> _dialogBuilder(BuildContext context, Object? arguments) {
/// return RawDialogRoute<void>(
/// pageBuilder: (
/// BuildContext context,
/// Animation<double> animation,
/// 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'),
/// ),
/// ),
/// );
/// }
/// static Route<Object?> _dialogBuilder(BuildContext context, Object? arguments) {
/// return RawDialogRoute<void>(
/// pageBuilder: (
/// BuildContext context,
/// Animation<double> animation,
/// Animation<double> secondaryAnimation,
/// ) {
/// return const AlertDialog(title: Text('Alert!'));
/// },
/// );
/// }
/// ```
///
......
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