[go: nahoru, domu]

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 2 commits into from
Mar 22, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// 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);
final Widget goodJob = const Text('Good job!');
gspencergoog marked this conversation as resolved.
Show resolved Hide resolved

@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),
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// 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'));
});
}
5 changes: 5 additions & 0 deletions packages/flutter/lib/src/widgets/tween_animation_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@ import 'value_listenable_builder.dart';
/// [AnimatedBuilder], which can be used similarly to this
/// [TweenAnimationBuilder], but unlike the latter it is powered by a
/// 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 {
/// Creates a [TweenAnimationBuilder].
///
Expand Down
60 changes: 5 additions & 55 deletions packages/flutter/lib/src/widgets/value_listenable_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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
/// 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
/// setting state on the whole [Scaffold] in the default `flutter create` app.
///
/// ```dart
/// class MyHomePage extends StatefulWidget {
/// const MyHomePage({super.key, required this.title});
/// final String title;
///
/// @override
/// State<MyHomePage> createState() => _MyHomePageState();
/// }
/// setting state on the whole [Scaffold] in a counter app.
///
/// class _MyHomePageState extends State<MyHomePage> {
/// 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,
/// ),
/// );
/// }
/// }
/// ```
/// ** See code in examples/api/lib/widgets/value_listenable_builder/value_listenable_builder.0.dart **
/// {@end-tool}
///
/// See also:
Expand All @@ -108,6 +56,8 @@ typedef ValueWidgetBuilder<T> = Widget Function(BuildContext context, T value, W
/// you have a direct reference to.
/// * [StreamBuilder], where a builder can depend on a [Stream] rather than
/// a [ValueListenable] for more advanced use cases.
/// * [TweenAnimationBuilder], which can animate values in a widget based on a
/// [Tween].
class ValueListenableBuilder<T> extends StatefulWidget {
/// Creates a [ValueListenableBuilder].
///
Expand Down