Add sample for InheritedNotifier, convert two others to DartPa… (#52349)
This adds a sample for InheritedNotifier, and converts a couple of other samples to be DartPad samples. I also added a new sample template stateful_widget_material_ticker, which adds a TickerProviderStateMixin to the state object so that animation controllers can be created there easily.
This commit is contained in:
parent
78b45fb1b2
commit
d19c44344b
@ -0,0 +1,35 @@
|
||||
// Flutter code sample for {{element}}
|
||||
|
||||
{{description}}
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
{{code-imports}}
|
||||
|
||||
void main() => runApp(new MyApp());
|
||||
|
||||
/// This Widget is the main application widget.
|
||||
class MyApp extends StatelessWidget {
|
||||
static const String _title = 'Flutter Code Sample';
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
title: _title,
|
||||
home: MyStatefulWidget(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
{{code-preamble}}
|
||||
|
||||
class MyStatefulWidget extends StatefulWidget {
|
||||
MyStatefulWidget({Key key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_MyStatefulWidgetState createState() => _MyStatefulWidgetState();
|
||||
}
|
||||
|
||||
class _MyStatefulWidgetState extends State<MyStatefulWidget> with TickerProviderStateMixin {
|
||||
{{code}}
|
||||
}
|
@ -38,9 +38,10 @@ import 'observer_list.dart';
|
||||
///
|
||||
/// * [AnimatedBuilder], a widget that uses a builder callback to rebuild
|
||||
/// whenever a given [Listenable] triggers its notifications. This widget is
|
||||
/// commonly used with [Animation] subclasses, wherein its name. It is a
|
||||
/// subclass of [AnimatedWidget], which can be used to create widgets that
|
||||
/// are driven from a [Listenable].
|
||||
/// commonly used with [Animation] subclasses, hence its name, but is by no
|
||||
/// means limited to animations, as it can be used with any [Listenable]. It
|
||||
/// is a subclass of [AnimatedWidget], which can be used to create widgets
|
||||
/// that are driven from a [Listenable].
|
||||
/// * [ValueListenableBuilder], a widget that uses a builder callback to
|
||||
/// rebuild whenever a [ValueListenable] object triggers its notifications,
|
||||
/// providing the builder with the value of the object.
|
||||
|
@ -28,6 +28,93 @@ import 'framework.dart';
|
||||
/// changed. When it returns true, the dependents are marked as needing to be
|
||||
/// rebuilt this frame.
|
||||
///
|
||||
/// {@tool dartpad --template=stateful_widget_material_ticker}
|
||||
///
|
||||
/// This example shows three spinning squares that use the value of the notifier
|
||||
/// on an ancestor [InheritedNotifier] (`SpinModel`) to give them their
|
||||
/// rotation. The [InheritedNotifier] doesn't need to know about the children,
|
||||
/// and the `notifier` argument doesn't need to be an animation controller, it
|
||||
/// can be anything that implements [Listenable] (like a [ChangeNotifier]).
|
||||
///
|
||||
/// The `SpinModel` class could just as easily listen to another object (say, a
|
||||
/// separate object that keeps the value of an input or data model value) that
|
||||
/// is a [Listenable], and get the value from that. The descendants also don't
|
||||
/// need to have an instance of the [InheritedNotifier] in order to use it, they
|
||||
/// just need to know that there is one in their ancestry. This can help with
|
||||
/// decoupling widgets from their models.
|
||||
///
|
||||
/// ```dart imports
|
||||
/// import 'dart:math' as math;
|
||||
/// ```
|
||||
///
|
||||
/// ```dart preamble
|
||||
/// class SpinModel extends InheritedNotifier<AnimationController> {
|
||||
/// SpinModel({
|
||||
/// Key key,
|
||||
/// AnimationController notifier,
|
||||
/// Widget child,
|
||||
/// }) : super(key: key, notifier: notifier, child: child);
|
||||
///
|
||||
/// static double of(BuildContext context) {
|
||||
/// return context.dependOnInheritedWidgetOfExactType<SpinModel>().notifier.value;
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// class Spinner extends StatelessWidget {
|
||||
/// const Spinner();
|
||||
///
|
||||
/// @override
|
||||
/// Widget build(BuildContext context) {
|
||||
/// return Transform.rotate(
|
||||
/// angle: SpinModel.of(context) * 2.0 * math.pi,
|
||||
/// child: Container(
|
||||
/// width: 100,
|
||||
/// height: 100,
|
||||
/// color: Colors.green,
|
||||
/// child: const Center(
|
||||
/// child: Text('Whee!'),
|
||||
/// ),
|
||||
/// ),
|
||||
/// );
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// ```dart
|
||||
/// AnimationController _controller;
|
||||
///
|
||||
/// @override
|
||||
/// void initState() {
|
||||
/// super.initState();
|
||||
/// _controller = AnimationController(
|
||||
/// duration: const Duration(seconds: 10),
|
||||
/// vsync: this,
|
||||
/// )..repeat();
|
||||
/// }
|
||||
///
|
||||
/// @override
|
||||
/// void dispose() {
|
||||
/// _controller.dispose();
|
||||
/// super.dispose();
|
||||
/// }
|
||||
///
|
||||
/// @override
|
||||
/// Widget build(BuildContext context) {
|
||||
/// return SpinModel(
|
||||
/// notifier: _controller,
|
||||
/// child: Row(
|
||||
/// mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
/// children: const <Widget>[
|
||||
/// Spinner(),
|
||||
/// Spinner(),
|
||||
/// Spinner(),
|
||||
/// ],
|
||||
/// ),
|
||||
/// );
|
||||
/// }
|
||||
/// ```
|
||||
/// {@end-tool}
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [Animation], an implementation of [Listenable] that ticks each frame to
|
||||
|
@ -23,41 +23,16 @@ export 'package:flutter/rendering.dart' show RelativeRect;
|
||||
/// [AnimatedWidget] is most useful for widgets that are otherwise stateless. To
|
||||
/// use [AnimatedWidget], simply subclass it and implement the build function.
|
||||
///
|
||||
///{@tool snippet}
|
||||
///{@tool dartpad --template=stateful_widget_material_ticker}
|
||||
///
|
||||
/// This code defines a widget called `Spinner` that spins a green square
|
||||
/// continually. It is built with an [AnimatedWidget].
|
||||
///
|
||||
/// ```dart
|
||||
/// class Spinner extends StatefulWidget {
|
||||
/// @override
|
||||
/// _SpinnerState createState() => _SpinnerState();
|
||||
/// }
|
||||
///
|
||||
/// class _SpinnerState extends State<Spinner> with TickerProviderStateMixin {
|
||||
/// AnimationController _controller;
|
||||
///
|
||||
/// @override
|
||||
/// void initState() {
|
||||
/// super.initState();
|
||||
/// _controller = AnimationController(
|
||||
/// duration: const Duration(seconds: 10),
|
||||
/// vsync: this,
|
||||
/// )..repeat();
|
||||
/// }
|
||||
///
|
||||
/// @override
|
||||
/// void dispose() {
|
||||
/// _controller.dispose();
|
||||
/// super.dispose();
|
||||
/// }
|
||||
///
|
||||
/// @override
|
||||
/// Widget build(BuildContext context) {
|
||||
/// return SpinningContainer(controller: _controller);
|
||||
/// }
|
||||
/// }
|
||||
/// ```dart imports
|
||||
/// import 'dart:math' as math;
|
||||
/// ```
|
||||
///
|
||||
/// ```dart preamble
|
||||
/// class SpinningContainer extends AnimatedWidget {
|
||||
/// const SpinningContainer({Key key, AnimationController controller})
|
||||
/// : super(key: key, listenable: controller);
|
||||
@ -73,6 +48,30 @@ export 'package:flutter/rendering.dart' show RelativeRect;
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// ```dart
|
||||
/// AnimationController _controller;
|
||||
///
|
||||
/// @override
|
||||
/// void initState() {
|
||||
/// super.initState();
|
||||
/// _controller = AnimationController(
|
||||
/// duration: const Duration(seconds: 10),
|
||||
/// vsync: this,
|
||||
/// )..repeat();
|
||||
/// }
|
||||
///
|
||||
/// @override
|
||||
/// void dispose() {
|
||||
/// _controller.dispose();
|
||||
/// super.dispose();
|
||||
/// }
|
||||
///
|
||||
/// @override
|
||||
/// Widget build(BuildContext context) {
|
||||
/// return SpinningContainer(controller: _controller);
|
||||
/// }
|
||||
/// ```
|
||||
/// {@end-tool}
|
||||
///
|
||||
/// For more complex case involving additional state, consider using
|
||||
@ -1035,63 +1034,57 @@ class DefaultTextStyleTransition extends AnimatedWidget {
|
||||
/// Using this pre-built child is entirely optional, but can improve
|
||||
/// performance significantly in some cases and is therefore a good practice.
|
||||
///
|
||||
/// {@tool snippet}
|
||||
/// {@tool dartpad --template=stateful_widget_material_ticker}
|
||||
///
|
||||
/// This code defines a widget called `Spinner` that spins a green square
|
||||
/// continually. It is built with an [AnimatedBuilder] and makes use of the
|
||||
/// [child] feature to avoid having to rebuild the [Container] each time. The
|
||||
/// resulting animation is shown below the code.
|
||||
/// This code defines a widget that spins a green square continually. It is
|
||||
/// built with an [AnimatedBuilder] and makes use of the [child] feature to
|
||||
/// avoid having to rebuild the [Container] each time.
|
||||
///
|
||||
/// ```dart imports
|
||||
/// import 'dart:math' as math;
|
||||
/// ```
|
||||
///
|
||||
/// ```dart
|
||||
/// class Spinner extends StatefulWidget {
|
||||
/// @override
|
||||
/// _SpinnerState createState() => _SpinnerState();
|
||||
/// AnimationController _controller;
|
||||
///
|
||||
/// @override
|
||||
/// void initState() {
|
||||
/// super.initState();
|
||||
/// _controller = AnimationController(
|
||||
/// duration: const Duration(seconds: 10),
|
||||
/// vsync: this,
|
||||
/// )..repeat();
|
||||
/// }
|
||||
///
|
||||
/// class _SpinnerState extends State<Spinner> with SingleTickerProviderStateMixin {
|
||||
/// AnimationController _controller;
|
||||
/// @override
|
||||
/// void dispose() {
|
||||
/// _controller.dispose();
|
||||
/// super.dispose();
|
||||
/// }
|
||||
///
|
||||
/// @override
|
||||
/// void initState() {
|
||||
/// super.initState();
|
||||
/// _controller = AnimationController(
|
||||
/// duration: const Duration(seconds: 10),
|
||||
/// vsync: this,
|
||||
/// )..repeat();
|
||||
/// }
|
||||
///
|
||||
/// @override
|
||||
/// void dispose() {
|
||||
/// _controller.dispose();
|
||||
/// super.dispose();
|
||||
/// }
|
||||
///
|
||||
/// @override
|
||||
/// Widget build(BuildContext context) {
|
||||
/// return AnimatedBuilder(
|
||||
/// animation: _controller,
|
||||
/// child: Container(
|
||||
/// width: 200.0,
|
||||
/// height: 200.0,
|
||||
/// color: Colors.green,
|
||||
/// child: const Center(
|
||||
/// child: Text('Wee'),
|
||||
/// ),
|
||||
/// @override
|
||||
/// Widget build(BuildContext context) {
|
||||
/// return AnimatedBuilder(
|
||||
/// animation: _controller,
|
||||
/// child: Container(
|
||||
/// width: 200.0,
|
||||
/// height: 200.0,
|
||||
/// color: Colors.green,
|
||||
/// child: const Center(
|
||||
/// child: Text('Whee!'),
|
||||
/// ),
|
||||
/// builder: (BuildContext context, Widget child) {
|
||||
/// return Transform.rotate(
|
||||
/// angle: _controller.value * 2.0 * math.pi,
|
||||
/// child: child,
|
||||
/// );
|
||||
/// },
|
||||
/// );
|
||||
/// }
|
||||
/// ),
|
||||
/// builder: (BuildContext context, Widget child) {
|
||||
/// return Transform.rotate(
|
||||
/// angle: _controller.value * 2.0 * math.pi,
|
||||
/// child: child,
|
||||
/// );
|
||||
/// },
|
||||
/// );
|
||||
/// }
|
||||
/// ```
|
||||
/// {@end-tool}
|
||||
///
|
||||
/// {@animation 300 300 https://flutter.github.io/assets-for-api-docs/assets/widgets/animated_builder.mp4}
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [TweenAnimationBuilder], which animates a property to a target value
|
||||
|
Loading…
x
Reference in New Issue
Block a user