Unverified Commit d19c4434 authored by Greg Spencer's avatar Greg Spencer Committed by GitHub

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.
parent 78b45fb1
// 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 initState() {
/// super.initState();
/// _controller = AnimationController(
/// duration: const Duration(seconds: 10),
/// vsync: this,
/// )..repeat();
/// }
///
/// @override
/// void dispose() {
/// _controller.dispose();
/// super.dispose();
/// }
/// @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
......
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