Unverified Commit 0f685f88 authored by Greg Spencer's avatar Greg Spencer Committed by GitHub

Add some cross references in the docs, move an example to a dartpad example (#145571)

## Description

This adds some "See also" links to some docs for `TweenAnimationBuilder` and `ValueListenableBuilder`.

Also, moved a "snippet" example in `ValueListenableBuilder` into the examples directory as a Dartpad example.

## Tests
 - Added test for the example.
parent 784f19c4
// 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';
/// Flutter code sample for [ValueListenableBuilder].
void main() => runApp(const ValueListenableBuilderExampleApp());
class ValueListenableBuilderExampleApp extends StatelessWidget {
const ValueListenableBuilderExampleApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: ValueListenableBuilderExample(),
);
}
}
class ValueListenableBuilderExample extends StatefulWidget {
const ValueListenableBuilderExample({super.key});
@override
State<ValueListenableBuilderExample> createState() => _ValueListenableBuilderExampleState();
}
class _ValueListenableBuilderExampleState extends State<ValueListenableBuilderExample> {
final ValueNotifier<int> _counter = ValueNotifier<int>(0);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('ValueListenableBuilder Sample'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text('You have pushed the button this many times:'),
ValueListenableBuilder<int>(
builder: (BuildContext context, int value, Widget? child) {
// This builder will only get called when the _counter
// is updated.
return Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
CountDisplay(count: value),
child!,
],
);
},
valueListenable: _counter,
// The child parameter is most helpful if the child is
// expensive to build and does not depend on the value from
// the notifier.
child: const Padding(
padding: EdgeInsets.all(10.0),
child: SizedBox(
width: 40,
height: 40,
child: FlutterLogo(size: 40),
),
),
),
],
),
),
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.plus_one),
onPressed: () => _counter.value += 1,
),
);
}
}
class CountDisplay extends StatelessWidget {
const CountDisplay({super.key, required this.count});
final int count;
@override
Widget build(BuildContext context) {
return Container(
width: 100,
height: 100,
padding: const EdgeInsetsDirectional.all(10),
child: Text('$count', style: Theme.of(context).textTheme.headline4),
);
}
}
// 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/value_listenable_builder/value_listenable_builder.0.dart' as example;
import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets('Tapping FAB increments counter', (WidgetTester tester) async {
await tester.pumpWidget(
const MaterialApp(
home: example.ValueListenableBuilderExample(),
),
);
String getCount() {
return (tester.widget(
find.descendant(
of: find.byType(example.CountDisplay),
matching: find.byType(Text),
),
) as Text).data!;
}
expect(find.text('You have pushed the button this many times:'), findsOneWidget);
expect(find.text('0'), findsOneWidget);
expect(find.byIcon(Icons.plus_one), findsOneWidget);
expect(getCount(), equals('0'));
await tester.tap(find.byType(FloatingActionButton).first);
await tester.pumpAndSettle();
expect(getCount(), equals('1'));
});
}
...@@ -90,6 +90,11 @@ import 'value_listenable_builder.dart'; ...@@ -90,6 +90,11 @@ import 'value_listenable_builder.dart';
/// [AnimatedBuilder], which can be used similarly to this /// [AnimatedBuilder], which can be used similarly to this
/// [TweenAnimationBuilder], but unlike the latter it is powered by a /// [TweenAnimationBuilder], but unlike the latter it is powered by a
/// developer-managed [AnimationController]. /// developer-managed [AnimationController].
///
/// See also:
///
/// * [ValueListenableBuilder], a widget whose content stays synced with a
/// [ValueListenable] instead of a [Tween].
class TweenAnimationBuilder<T extends Object?> extends ImplicitlyAnimatedWidget { class TweenAnimationBuilder<T extends Object?> extends ImplicitlyAnimatedWidget {
/// Creates a [TweenAnimationBuilder]. /// Creates a [TweenAnimationBuilder].
/// ///
......
...@@ -40,63 +40,11 @@ typedef ValueWidgetBuilder<T> = Widget Function(BuildContext context, T value, W ...@@ -40,63 +40,11 @@ typedef ValueWidgetBuilder<T> = Widget Function(BuildContext context, T value, W
/// Using this pre-built child is entirely optional, but can improve /// Using this pre-built child is entirely optional, but can improve
/// performance significantly in some cases and is therefore a good practice. /// performance significantly in some cases and is therefore a good practice.
/// ///
/// {@tool snippet} /// {@tool dartpad}
///
/// This sample shows how you could use a [ValueListenableBuilder] instead of /// This sample shows how you could use a [ValueListenableBuilder] instead of
/// setting state on the whole [Scaffold] in the default `flutter create` app. /// setting state on the whole [Scaffold] in a counter app.
///
/// ```dart
/// class MyHomePage extends StatefulWidget {
/// const MyHomePage({super.key, required this.title});
/// final String title;
///
/// @override
/// State<MyHomePage> createState() => _MyHomePageState();
/// }
/// ///
/// class _MyHomePageState extends State<MyHomePage> { /// ** See code in examples/api/lib/widgets/value_listenable_builder/value_listenable_builder.0.dart **
/// final ValueNotifier<int> _counter = ValueNotifier<int>(0);
/// final Widget goodJob = const Text('Good job!');
/// @override
/// Widget build(BuildContext context) {
/// return Scaffold(
/// appBar: AppBar(
/// title: Text(widget.title)
/// ),
/// body: Center(
/// child: Column(
/// mainAxisAlignment: MainAxisAlignment.center,
/// children: <Widget>[
/// const Text('You have pushed the button this many times:'),
/// ValueListenableBuilder<int>(
/// builder: (BuildContext context, int value, Widget? child) {
/// // This builder will only get called when the _counter
/// // is updated.
/// return Row(
/// mainAxisAlignment: MainAxisAlignment.spaceEvenly,
/// children: <Widget>[
/// Text('$value'),
/// child!,
/// ],
/// );
/// },
/// valueListenable: _counter,
/// // The child parameter is most helpful if the child is
/// // expensive to build and does not depend on the value from
/// // the notifier.
/// child: goodJob,
/// )
/// ],
/// ),
/// ),
/// floatingActionButton: FloatingActionButton(
/// child: const Icon(Icons.plus_one),
/// onPressed: () => _counter.value += 1,
/// ),
/// );
/// }
/// }
/// ```
/// {@end-tool} /// {@end-tool}
/// ///
/// See also: /// See also:
...@@ -108,6 +56,8 @@ typedef ValueWidgetBuilder<T> = Widget Function(BuildContext context, T value, W ...@@ -108,6 +56,8 @@ typedef ValueWidgetBuilder<T> = Widget Function(BuildContext context, T value, W
/// you have a direct reference to. /// you have a direct reference to.
/// * [StreamBuilder], where a builder can depend on a [Stream] rather than /// * [StreamBuilder], where a builder can depend on a [Stream] rather than
/// a [ValueListenable] for more advanced use cases. /// a [ValueListenable] for more advanced use cases.
/// * [TweenAnimationBuilder], which can animate values in a widget based on a
/// [Tween].
class ValueListenableBuilder<T> extends StatefulWidget { class ValueListenableBuilder<T> extends StatefulWidget {
/// Creates a [ValueListenableBuilder]. /// Creates a [ValueListenableBuilder].
/// ///
......
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