mirror of
https://github.com/flutter/flutter
synced 2024-08-27 12:00:58 +00:00
parent
98a3055010
commit
3fe5740153
|
@ -2,12 +2,37 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flutter code sample for a [ChangeNotifier] with a [ListenableBuilder].
|
||||
// Flutter code sample for a [ValueNotifier] with a [ListenableBuilder].
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
void main() { runApp(const ListenableBuilderExample()); }
|
||||
|
||||
class ListenableBuilderExample extends StatefulWidget {
|
||||
const ListenableBuilderExample({super.key});
|
||||
|
||||
@override
|
||||
State<ListenableBuilderExample> createState() => _ListenableBuilderExampleState();
|
||||
}
|
||||
|
||||
class _ListenableBuilderExampleState extends State<ListenableBuilderExample> {
|
||||
final ValueNotifier<int> _counter = ValueNotifier<int>(0);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
home: Scaffold(
|
||||
appBar: AppBar(title: const Text('ListenableBuilder Example')),
|
||||
body: CounterBody(counterValueNotifier: _counter),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: () => _counter.value++,
|
||||
child: const Icon(Icons.add),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class CounterBody extends StatelessWidget {
|
||||
const CounterBody({super.key, required this.counterValueNotifier});
|
||||
|
||||
|
@ -35,28 +60,3 @@ class CounterBody extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ListenableBuilderExample extends StatefulWidget {
|
||||
const ListenableBuilderExample({super.key});
|
||||
|
||||
@override
|
||||
State<ListenableBuilderExample> createState() => _ListenableBuilderExampleState();
|
||||
}
|
||||
|
||||
class _ListenableBuilderExampleState extends State<ListenableBuilderExample> {
|
||||
final ValueNotifier<int> _counter = ValueNotifier<int>(0);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
home: Scaffold(
|
||||
appBar: AppBar(title: const Text('ListenableBuilder Example')),
|
||||
body: CounterBody(counterValueNotifier: _counter),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: () => _counter.value++,
|
||||
child: const Icon(Icons.add),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
// 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.
|
||||
|
||||
// Flutter code sample for a [ChangeNotifier] with a [ListenableBuilder].
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
void main() { runApp(const ListenableBuilderExample()); }
|
||||
|
||||
class CounterModel with ChangeNotifier {
|
||||
int _count = 0;
|
||||
int get count => _count;
|
||||
|
||||
void increment() {
|
||||
_count += 1;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
class ListenableBuilderExample extends StatefulWidget {
|
||||
const ListenableBuilderExample({super.key});
|
||||
|
||||
@override
|
||||
State<ListenableBuilderExample> createState() => _ListenableBuilderExampleState();
|
||||
}
|
||||
|
||||
class _ListenableBuilderExampleState extends State<ListenableBuilderExample> {
|
||||
final CounterModel _counter = CounterModel();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
home: Scaffold(
|
||||
appBar: AppBar(title: const Text('ListenableBuilder Example')),
|
||||
body: CounterBody(counterNotifier: _counter),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: _counter.increment,
|
||||
child: const Icon(Icons.add),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class CounterBody extends StatelessWidget {
|
||||
const CounterBody({super.key, required this.counterNotifier});
|
||||
|
||||
final CounterModel counterNotifier;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
const Text('Current counter value:'),
|
||||
// Thanks to the ListenableBuilder, only the widget displaying the
|
||||
// current count is rebuilt when counterValueNotifier notifies its
|
||||
// listeners. The Text widget above and CounterBody itself aren't
|
||||
// rebuilt.
|
||||
ListenableBuilder(
|
||||
listenable: counterNotifier,
|
||||
builder: (BuildContext context, Widget? child) {
|
||||
return Text('${counterNotifier.count}');
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
// 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.
|
||||
|
||||
// Flutter code sample for a [ChangeNotifier] with a [ListenableBuilder].
|
||||
|
||||
import 'dart:math' as math;
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
void main() { runApp(const ListenableBuilderExample()); }
|
||||
|
||||
class ListModel with ChangeNotifier {
|
||||
final List<int> _values = <int>[];
|
||||
List<int> get values => _values.toList(); // O(N), makes a new copy each time.
|
||||
|
||||
void add(int value) {
|
||||
_values.add(value);
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
class ListenableBuilderExample extends StatefulWidget {
|
||||
const ListenableBuilderExample({super.key});
|
||||
|
||||
@override
|
||||
State<ListenableBuilderExample> createState() => _ListenableBuilderExampleState();
|
||||
}
|
||||
|
||||
class _ListenableBuilderExampleState extends State<ListenableBuilderExample> {
|
||||
final ListModel _listNotifier = ListModel();
|
||||
final math.Random _random = math.Random(0); // fixed seed for reproducability
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
home: Scaffold(
|
||||
appBar: AppBar(title: const Text('ListenableBuilder Example')),
|
||||
body: ListBody(listNotifier: _listNotifier),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: () => _listNotifier.add(_random.nextInt(1 << 32)), // 1 << 32 is the maximum supported value
|
||||
child: const Icon(Icons.add),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ListBody extends StatelessWidget {
|
||||
const ListBody({super.key, required this.listNotifier});
|
||||
|
||||
final ListModel listNotifier;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Center(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: <Widget>[
|
||||
const Text('Current values:'),
|
||||
Expanded(
|
||||
child: ListenableBuilder(
|
||||
listenable: listNotifier,
|
||||
builder: (BuildContext context, Widget? child) {
|
||||
// We rebuild the ListView each time the list changes,
|
||||
// so that the framework knows to update the rendering.
|
||||
final List<int> values = listNotifier.values; // copy the list
|
||||
return ListView.builder(
|
||||
itemBuilder: (BuildContext context, int index) => ListTile(
|
||||
title: Text('${values[index]}'),
|
||||
),
|
||||
itemCount: values.length,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -667,15 +667,18 @@ class AnimationController extends Animation<double>
|
|||
/// and initial velocity.
|
||||
///
|
||||
/// If velocity is positive, the animation will complete, otherwise it will
|
||||
/// dismiss.
|
||||
/// dismiss. The velocity is specified in units per second. If the
|
||||
/// [SemanticsBinding.disableAnimations] flag is set, the velocity is somewhat
|
||||
/// arbitrarily multiplied by 200.
|
||||
///
|
||||
/// The [springDescription] parameter can be used to specify a custom [SpringType.criticallyDamped]
|
||||
/// or [SpringType.overDamped] spring to drive the animation with. Defaults to null, which uses a
|
||||
/// [SpringType.criticallyDamped] spring. See [SpringDescription.withDampingRatio] for how
|
||||
/// to create a suitable [SpringDescription].
|
||||
/// The [springDescription] parameter can be used to specify a custom
|
||||
/// [SpringType.criticallyDamped] or [SpringType.overDamped] spring with which
|
||||
/// to drive the animation. By default, a [SpringType.criticallyDamped] spring
|
||||
/// is used. See [SpringDescription.withDampingRatio] for how to create a
|
||||
/// suitable [SpringDescription].
|
||||
///
|
||||
/// The resulting spring simulation cannot be of type [SpringType.underDamped],
|
||||
/// as this can lead to unexpected look of the produced animation.
|
||||
/// The resulting spring simulation cannot be of type [SpringType.underDamped];
|
||||
/// such a spring would oscillate rather than fling.
|
||||
///
|
||||
/// Returns a [TickerFuture] that completes when the animation is complete.
|
||||
///
|
||||
|
@ -692,9 +695,7 @@ class AnimationController extends Animation<double>
|
|||
if (SemanticsBinding.instance.disableAnimations) {
|
||||
switch (behavior) {
|
||||
case AnimationBehavior.normal:
|
||||
// TODO(zanderso): determine a better process for setting velocity.
|
||||
// the value below was arbitrarily chosen because it worked for the drawer widget.
|
||||
scale = 200.0;
|
||||
scale = 200.0; // This is arbitrary (it was chosen because it worked for the drawer widget).
|
||||
break;
|
||||
case AnimationBehavior.preserve:
|
||||
break;
|
||||
|
@ -704,8 +705,10 @@ class AnimationController extends Animation<double>
|
|||
..tolerance = _kFlingTolerance;
|
||||
assert(
|
||||
simulation.type != SpringType.underDamped,
|
||||
'The resulting spring simulation is of type SpringType.underDamped.\n'
|
||||
'This can lead to unexpected look of the animation, please adjust the springDescription parameter',
|
||||
'The specified spring simulation is of type SpringType.underDamped.\n'
|
||||
'An underdamped spring results in oscillation rather than a fling. '
|
||||
'Consider specifying a different springDescription, or use animateWith() '
|
||||
'with an explicit SpringSimulation if an underdamped spring is intentional.',
|
||||
);
|
||||
stop();
|
||||
return _startSimulation(simulation);
|
||||
|
|
|
@ -104,7 +104,29 @@ const String _flutterFoundationLibrary = 'package:flutter/foundation.dart';
|
|||
/// It is O(1) for adding listeners and O(N) for removing listeners and dispatching
|
||||
/// notifications (where N is the number of listeners).
|
||||
///
|
||||
/// {@macro flutter.flutter.ListenableBuilder.ChangeNotifier.rebuild}
|
||||
/// ## Using ChangeNotifier subclasses for data models
|
||||
///
|
||||
/// A data structure can extend or mix in [ChangeNotifier] to implement the
|
||||
/// [Listenable] interface and thus become usable with widgets that listen for
|
||||
/// changes to [Listenable]s, such as [ListenableBuilder].
|
||||
///
|
||||
/// {@tool dartpad}
|
||||
/// The following example implements a simple counter that utilizes a
|
||||
/// [ListenableBuilder] to limit rebuilds to only the [Text] widget containing
|
||||
/// the count. The current count is stored in a [ChangeNotifier] subclass, which
|
||||
/// rebuilds the [ListenableBuilder]'s contents when its value is changed.
|
||||
///
|
||||
/// ** See code in examples/api/lib/widgets/transitions/listenable_builder.2.dart **
|
||||
/// {@end-tool}
|
||||
///
|
||||
/// {@tool dartpad}
|
||||
/// In this case, the [ChangeNotifier] subclass encapsulates a list, and notifies
|
||||
/// the clients any time an item is added to the list. This example only supports
|
||||
/// adding items; as an exercise, consider adding buttons to remove items from
|
||||
/// the list as well.
|
||||
///
|
||||
/// ** See code in examples/api/lib/widgets/transitions/listenable_builder.3.dart **
|
||||
/// {@end-tool}
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
|
@ -466,6 +488,19 @@ class _MergingListenable extends Listenable {
|
|||
/// When [value] is replaced with something that is not equal to the old
|
||||
/// value as evaluated by the equality operator ==, this class notifies its
|
||||
/// listeners.
|
||||
///
|
||||
/// ## Limitations
|
||||
///
|
||||
/// Because this class only notifies listeners when the [value]'s _identity_
|
||||
/// changes, listeners will not be notified when mutable state within the
|
||||
/// value itself changes.
|
||||
///
|
||||
/// For example, a `ValueNotifier<List<int>>` will not notify its listeners
|
||||
/// when the _contents_ of the list are changed.
|
||||
///
|
||||
/// As a result, this class is best used with only immutable data types.
|
||||
///
|
||||
/// For mutable data types, consider extending [ChangeNotifier] directly.
|
||||
class ValueNotifier<T> extends ChangeNotifier implements ValueListenable<T> {
|
||||
/// Creates a [ChangeNotifier] that wraps this value.
|
||||
ValueNotifier(this._value) {
|
||||
|
|
|
@ -2162,7 +2162,7 @@ class FlagProperty extends DiagnosticsProperty<bool> {
|
|||
if (value == null || ((value ?? false) && ifTrue == null) || (!(value ?? true) && ifFalse == null)) {
|
||||
// We are missing a description for the flag value so we need to show the
|
||||
// flag name. The property will have DiagnosticLevel.hidden for this case
|
||||
// so users will not see this the property in this case unless they are
|
||||
// so users will not see this property in this case unless they are
|
||||
// displaying hidden properties.
|
||||
return true;
|
||||
}
|
||||
|
@ -2379,7 +2379,7 @@ class ObjectFlagProperty<T> extends DiagnosticsProperty<T> {
|
|||
if ((value != null && ifPresent == null) || (value == null && ifNull == null)) {
|
||||
// We are missing a description for the flag value so we need to show the
|
||||
// flag name. The property will have DiagnosticLevel.hidden for this case
|
||||
// so users will not see this the property in this case unless they are
|
||||
// so users will not see this property in this case unless they are
|
||||
// displaying hidden properties.
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -81,8 +81,8 @@ class BottomAppBar extends StatefulWidget {
|
|||
///
|
||||
/// {@macro flutter.widgets.ProxyWidget.child}
|
||||
///
|
||||
/// Typically this the child will be a [Row], with the first child
|
||||
/// being an [IconButton] with the [Icons.menu] icon.
|
||||
/// Typically the child will be a [Row] whose first child
|
||||
/// is an [IconButton] with the [Icons.menu] icon.
|
||||
final Widget? child;
|
||||
|
||||
/// The amount of space to surround the child inside the bounds of the [BottomAppBar].
|
||||
|
|
|
@ -2837,7 +2837,7 @@ class _InputDateRangePicker extends StatefulWidget {
|
|||
/// {@macro flutter.widgets.editableText.autofocus}
|
||||
final bool autofocus;
|
||||
|
||||
/// If true, this the date fields will validate and update their error text
|
||||
/// If true, the date fields will validate and update their error text
|
||||
/// immediately after every change. Otherwise, you must call
|
||||
/// [_InputDateRangePickerState.validate] to validate.
|
||||
final bool autovalidate;
|
||||
|
|
|
@ -272,15 +272,6 @@ class Dialog extends StatelessWidget {
|
|||
///
|
||||
/// {@youtube 560 315 https://www.youtube.com/watch?v=75CsnyRXf5I}
|
||||
///
|
||||
/// If the content is too large to fit on the screen vertically, the dialog will
|
||||
/// display the title and the actions and let the content overflow, which is
|
||||
/// rarely desired. Consider using a scrolling widget for [content], such as
|
||||
/// [SingleChildScrollView], to avoid overflow. (However, be aware that since
|
||||
/// [AlertDialog] tries to size itself using the intrinsic dimensions of its
|
||||
/// children, widgets such as [ListView], [GridView], and [CustomScrollView],
|
||||
/// which use lazy viewports, will not work. If this is a problem, consider
|
||||
/// using [Dialog] directly.)
|
||||
///
|
||||
/// For dialogs that offer the user a choice between several options, consider
|
||||
/// using a [SimpleDialog].
|
||||
///
|
||||
|
@ -340,6 +331,24 @@ class Dialog extends StatelessWidget {
|
|||
/// ** See code in examples/api/lib/material/dialog/alert_dialog.1.dart **
|
||||
/// {@end-tool}
|
||||
///
|
||||
/// ## Alert dialogs and scrolling
|
||||
///
|
||||
/// By default, alert dialogs size themselves to contain their children.
|
||||
///
|
||||
/// If the content is too large to fit on the screen vertically, the dialog will
|
||||
/// display the title and actions, and let the _[content]_ overflow. This is
|
||||
/// rarely desired. Consider using a scrolling widget for [content], such as
|
||||
/// [SingleChildScrollView], to avoid overflow.
|
||||
///
|
||||
/// Because the dialog attempts to size itself to the contents, the [content]
|
||||
/// must support reporting its intrinsic dimensions. In particular, this means
|
||||
/// that lazily-rendered widgets such as [ListView], [GridView], and
|
||||
/// [CustomScrollView], will not work in an [AlertDialog] unless they are
|
||||
/// wrapped in a widget that forces a particular size (e.g. a [SizedBox]).
|
||||
///
|
||||
/// For finer-grained control over the sizing of a dialog, consider using
|
||||
/// [Dialog] directly.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [SimpleDialog], which handles the scrolling of the contents but has no [actions].
|
||||
|
@ -441,7 +450,12 @@ class AlertDialog extends StatelessWidget {
|
|||
/// Typically this is a [SingleChildScrollView] that contains the dialog's
|
||||
/// message. As noted in the [AlertDialog] documentation, it's important
|
||||
/// to use a [SingleChildScrollView] if there's any risk that the content
|
||||
/// will not fit.
|
||||
/// will not fit, as the contents will otherwise overflow the dialog.
|
||||
///
|
||||
/// The [content] must support reporting its intrinsic dimensions. In
|
||||
/// particular, [ListView], [GridView], and [CustomScrollView] cannot be used
|
||||
/// here unless they are first wrapped in a widget that itself can report
|
||||
/// intrinsic dimensions, such as a [SizedBox].
|
||||
final Widget? content;
|
||||
|
||||
/// Padding around the content.
|
||||
|
|
|
@ -320,6 +320,9 @@ class ImageCache {
|
|||
/// `onError` is also provided. When an exception is caught resolving an image,
|
||||
/// no completers are cached and `null` is returned instead of a new
|
||||
/// completer.
|
||||
///
|
||||
/// Images that are larger than [maximumSizeBytes] are not cached, and do not
|
||||
/// cause other images in the cache to be evicted.
|
||||
ImageStreamCompleter? putIfAbsent(Object key, ImageStreamCompleter Function() loader, { ImageErrorListener? onError }) {
|
||||
TimelineTask? timelineTask;
|
||||
TimelineTask? listenerTask;
|
||||
|
|
|
@ -88,8 +88,9 @@ class StarBorder extends OutlinedBorder {
|
|||
/// This is a floating point number: if this is not a whole number, then an
|
||||
/// additional star point or corner shorter than the others will be added to
|
||||
/// finish the shape. Only whole-numbered values will yield a symmetric shape.
|
||||
/// (This enables the number of points to be animated smoothly.)
|
||||
///
|
||||
/// For stars created with [StarBorder], this the number of points on
|
||||
/// For stars created with [StarBorder], this is the number of points on
|
||||
/// the star. For polygons created with [StarBorder.polygon], this is the
|
||||
/// number of sides on the polygon.
|
||||
///
|
||||
|
|
|
@ -477,12 +477,17 @@ class RenderCustomPaint extends RenderProxyBox {
|
|||
/// The compositor contains a raster cache that holds bitmaps of layers in
|
||||
/// order to avoid the cost of repeatedly rendering those layers on each
|
||||
/// frame. If this flag is not set, then the compositor will apply its own
|
||||
/// heuristics to decide whether the this layer is complex enough to benefit
|
||||
/// from caching.
|
||||
/// heuristics to decide whether the layer containing this render object is
|
||||
/// complex enough to benefit from caching.
|
||||
bool isComplex;
|
||||
|
||||
/// Whether the raster cache should be told that this painting is likely
|
||||
/// to change in the next frame.
|
||||
///
|
||||
/// This hint tells the compositor not to cache the layer containing this
|
||||
/// render object because the cache will not be used in the future. If this
|
||||
/// hint is not set, the compositor will apply its own heuristics to decide
|
||||
/// whether this layer is likely to be reused in the future.
|
||||
bool willChange;
|
||||
|
||||
@override
|
||||
|
|
|
@ -901,7 +901,7 @@ class TextureLayer extends Layer {
|
|||
///
|
||||
/// This is used for resizing embedded Android views: when resizing there
|
||||
/// is a short period during which the framework cannot tell if the newest
|
||||
/// texture frame has the previous or new size, to workaround this the
|
||||
/// texture frame has the previous or new size; to work around this, the
|
||||
/// framework "freezes" the texture just before resizing the Android view and
|
||||
/// un-freezes it when it is certain that a frame with the new size is ready.
|
||||
final bool freeze;
|
||||
|
|
|
@ -4386,7 +4386,7 @@ abstract class _InterestingSemanticsFragment extends _SemanticsFragment {
|
|||
/// Disallows this fragment to merge any configuration into its parent's
|
||||
/// [SemanticsNode].
|
||||
///
|
||||
/// After calling this the fragment will only produce children to be added
|
||||
/// After calling this, the fragment will only produce children to be added
|
||||
/// to the parent and it will return null for [config].
|
||||
void markAsExplicit();
|
||||
|
||||
|
|
|
@ -55,6 +55,13 @@ abstract class AssetBundle {
|
|||
/// Retrieve a binary resource from the asset bundle as a data stream.
|
||||
///
|
||||
/// Throws an exception if the asset is not found.
|
||||
///
|
||||
/// The returned [ByteData] can be converted to a [Uint8List] (a list of bytes)
|
||||
/// using [ByteData.buffer] to obtain a [ByteBuffer], and then
|
||||
/// [ByteBuffer.asUint8List] to obtain the byte list. Lists of bytes can be
|
||||
/// used with APIs that accept [Uint8List] objects, such as
|
||||
/// [decodeImageFromList], as well as any API that accepts a [List<int>], such
|
||||
/// as [File.writeAsBytes] or [Utf8Codec.decode] (accessible via [utf8]).
|
||||
Future<ByteData> load(String key);
|
||||
|
||||
/// Retrieve a binary resource from the asset bundle as an immutable
|
||||
|
|
|
@ -15,11 +15,17 @@ import 'framework.dart';
|
|||
import 'media_query.dart';
|
||||
import 'shortcuts.dart';
|
||||
|
||||
// BuildContext/Element doesn't have a parent accessor, but it can be
|
||||
// simulated with visitAncestorElements. _getParent is needed because
|
||||
// context.getElementForInheritedWidgetOfExactType will return itself if it
|
||||
// happens to be of the correct type. getParent should be O(1), since we
|
||||
// always return false at the first ancestor.
|
||||
/// Returns the parent [BuildContext] of a given `context`.
|
||||
///
|
||||
/// [BuildContext] (or rather, [Element]) doesn't have a `parent` accessor, but
|
||||
/// the parent can be obtained using [BuildContext.visitAncestorElements].
|
||||
///
|
||||
/// [BuildContext.getElementForInheritedWidgetOfExactType] returns the same
|
||||
/// [BuildContext] if it happens to be of the correct type. To obtain the
|
||||
/// previous inherited widget, the search must therefore start from the parent;
|
||||
/// this is what [_getParent] is used for.
|
||||
///
|
||||
/// [_getParent] is O(1), because it always stops at the first ancestor.
|
||||
BuildContext _getParent(BuildContext context) {
|
||||
late final BuildContext parent;
|
||||
context.visitAncestorElements((Element ancestor) {
|
||||
|
@ -279,7 +285,7 @@ abstract class Action<T extends Intent> with Diagnosticable {
|
|||
/// This method is only meant to be invoked by an [ActionDispatcher], or by
|
||||
/// its subclasses, and only when [isEnabled] is true.
|
||||
///
|
||||
/// When overriding this method, the returned value can be any Object, but
|
||||
/// When overriding this method, the returned value can be any [Object], but
|
||||
/// changing the return type of the override to match the type of the returned
|
||||
/// value provides more type safety.
|
||||
///
|
||||
|
@ -527,7 +533,11 @@ abstract class ContextAction<T extends Intent> extends Action<T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// The signature of a callback accepted by [CallbackAction].
|
||||
/// The signature of a callback accepted by [CallbackAction.onInvoke].
|
||||
///
|
||||
/// Such callbacks are implementions of [Action.invoke]. The returned value
|
||||
/// is the return value of [Action.invoke], the argument is the intent passed
|
||||
/// to [Action.invoke], and so forth.
|
||||
typedef OnInvokeCallback<T extends Intent> = Object? Function(T intent);
|
||||
|
||||
/// An [Action] that takes a callback in order to configure it without having to
|
||||
|
@ -544,13 +554,12 @@ typedef OnInvokeCallback<T extends Intent> = Object? Function(T intent);
|
|||
class CallbackAction<T extends Intent> extends Action<T> {
|
||||
/// A constructor for a [CallbackAction].
|
||||
///
|
||||
/// The `intentKey` and [onInvoke] parameters must not be null.
|
||||
/// The [onInvoke] parameter is required.
|
||||
/// The given callback is used as the implementation of [invoke].
|
||||
CallbackAction({required this.onInvoke});
|
||||
|
||||
/// The callback to be called when invoked.
|
||||
///
|
||||
/// Must not be null.
|
||||
/// This is effectively the implementation of [invoke].
|
||||
@protected
|
||||
final OnInvokeCallback<T> onInvoke;
|
||||
|
||||
|
@ -716,6 +725,10 @@ class Actions extends StatefulWidget {
|
|||
/// Creates a dependency on the [Actions] widget that maps the bound action so
|
||||
/// that if the actions change, the context will be rebuilt and find the
|
||||
/// updated action.
|
||||
///
|
||||
/// The value returned from the [Action.invoke] method is discarded when the
|
||||
/// returned callback is called. If the return value is needed, consider using
|
||||
/// [Actions.invoke] instead.
|
||||
static VoidCallback? handler<T extends Intent>(BuildContext context, T intent) {
|
||||
final Action<T>? action = Actions.maybeFind<T>(context);
|
||||
if (action != null && action.isEnabled(intent)) {
|
||||
|
|
|
@ -442,8 +442,6 @@ class StreamBuilder<T> extends StreamBuilderBase<T, AsyncSnapshot<T>> {
|
|||
/// A widget that builds itself based on the latest snapshot of interaction with
|
||||
/// a [Future].
|
||||
///
|
||||
/// {@youtube 560 315 https://www.youtube.com/watch?v=ek8ZPdWj4Qo}
|
||||
///
|
||||
/// {@youtube 560 315 https://www.youtube.com/watch?v=zEdw_1B7JHY}
|
||||
///
|
||||
/// ## Managing the future
|
||||
|
@ -516,7 +514,6 @@ class StreamBuilder<T> extends StreamBuilderBase<T, AsyncSnapshot<T>> {
|
|||
///
|
||||
/// ** See code in examples/api/lib/widgets/async/future_builder.0.dart **
|
||||
/// {@end-tool}
|
||||
// TODO(ianh): remove unreachable code above once https://github.com/dart-lang/sdk/issues/35520 is fixed
|
||||
class FutureBuilder<T> extends StatefulWidget {
|
||||
/// Creates a widget that builds itself based on the latest snapshot of
|
||||
/// interaction with a [Future].
|
||||
|
|
|
@ -252,7 +252,12 @@ class Directionality extends _UbiquitousInheritedWidget {
|
|||
///
|
||||
/// Animating an [Opacity] widget directly causes the widget (and possibly its
|
||||
/// subtree) to rebuild each frame, which is not very efficient. Consider using
|
||||
/// an [AnimatedOpacity] or a [FadeTransition] instead.
|
||||
/// one of these alternative widgets instead:
|
||||
///
|
||||
/// * [AnimatedOpacity], which uses an animation internally to efficiently
|
||||
/// animate opacity.
|
||||
/// * [FadeTransition], which uses a provided animation to efficiently animate
|
||||
/// opacity.
|
||||
///
|
||||
/// ## Transparent image
|
||||
///
|
||||
|
@ -294,12 +299,7 @@ class Directionality extends _UbiquitousInheritedWidget {
|
|||
/// * [ShaderMask], which can apply more elaborate effects to its child.
|
||||
/// * [Transform], which applies an arbitrary transform to its child widget at
|
||||
/// paint time.
|
||||
/// * [AnimatedOpacity], which uses an animation internally to efficiently
|
||||
/// animate opacity.
|
||||
/// * [FadeTransition], which uses a provided animation to efficiently animate
|
||||
/// opacity.
|
||||
/// * [Image], which can directly provide a partially transparent image with
|
||||
/// much less performance hit.
|
||||
/// * [SliverOpacity], the sliver version of this widget.
|
||||
class Opacity extends SingleChildRenderObjectWidget {
|
||||
/// Creates a widget that makes its child partially transparent.
|
||||
///
|
||||
|
@ -600,8 +600,7 @@ class BackdropFilter extends SingleChildRenderObjectWidget {
|
|||
/// a child, they attempt to size themselves to the [size], which defaults to
|
||||
/// [Size.zero]. [size] must not be null.
|
||||
///
|
||||
/// [isComplex] and [willChange] are hints to the compositor's raster cache
|
||||
/// and must not be null.
|
||||
/// [isComplex] and [willChange] are hints to the compositor's raster cache.
|
||||
///
|
||||
/// {@tool snippet}
|
||||
///
|
||||
|
@ -662,8 +661,8 @@ class CustomPaint extends SingleChildRenderObjectWidget {
|
|||
/// The compositor contains a raster cache that holds bitmaps of layers in
|
||||
/// order to avoid the cost of repeatedly rendering those layers on each
|
||||
/// frame. If this flag is not set, then the compositor will apply its own
|
||||
/// heuristics to decide whether the this layer is complex enough to benefit
|
||||
/// from caching.
|
||||
/// heuristics to decide whether the layer containing this widget is complex
|
||||
/// enough to benefit from caching.
|
||||
///
|
||||
/// This flag can't be set to true if both [painter] and [foregroundPainter]
|
||||
/// are null because this flag will be ignored in such case.
|
||||
|
@ -672,6 +671,11 @@ class CustomPaint extends SingleChildRenderObjectWidget {
|
|||
/// Whether the raster cache should be told that this painting is likely
|
||||
/// to change in the next frame.
|
||||
///
|
||||
/// This hint tells the compositor not to cache the layer containing this
|
||||
/// widget because the cache will not be used in the future. If this hint is
|
||||
/// not set, the compositor will apply its own heuristics to decide whether
|
||||
/// the layer is likely to be reused in the future.
|
||||
///
|
||||
/// This flag can't be set to true if both [painter] and [foregroundPainter]
|
||||
/// are null because this flag will be ignored in such case.
|
||||
final bool willChange;
|
||||
|
@ -1920,9 +1924,10 @@ class RotatedBox extends SingleChildRenderObjectWidget {
|
|||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [EdgeInsets], the class that is used to describe the padding dimensions.
|
||||
/// * [AnimatedPadding], which animates changes in [padding] over a given
|
||||
/// duration.
|
||||
/// * [EdgeInsets], the class that is used to describe the padding dimensions.
|
||||
/// * [SliverPadding], the sliver equivalent of this widget.
|
||||
/// * The [catalog of layout widgets](https://flutter.dev/widgets/layout/).
|
||||
class Padding extends SingleChildRenderObjectWidget {
|
||||
/// Creates a widget that insets its child.
|
||||
|
@ -3216,6 +3221,7 @@ class SizedOverflowBox extends SingleChildRenderObjectWidget {
|
|||
/// * [Visibility], which can hide a child more efficiently (albeit less
|
||||
/// subtly).
|
||||
/// * [TickerMode], which can be used to disable animations in a subtree.
|
||||
/// * [SliverOffstage], the sliver version of this widget.
|
||||
/// * The [catalog of layout widgets](https://flutter.dev/widgets/layout/).
|
||||
class Offstage extends SingleChildRenderObjectWidget {
|
||||
/// Creates a widget that visually hides its child.
|
||||
|
@ -3267,56 +3273,72 @@ class _OffstageElement extends SingleChildRenderObjectElement {
|
|||
|
||||
/// A widget that attempts to size the child to a specific aspect ratio.
|
||||
///
|
||||
/// The widget first tries the largest width permitted by the layout
|
||||
/// constraints. The height of the widget is determined by applying the
|
||||
/// given aspect ratio to the width, expressed as a ratio of width to height.
|
||||
/// The aspect ratio is expressed as a ratio of width to height. For example, a
|
||||
/// 16:9 width:height aspect ratio would have a value of 16.0/9.0.
|
||||
///
|
||||
/// {@youtube 560 315 https://www.youtube.com/watch?v=XcnP3_mO_Ms}
|
||||
///
|
||||
/// For example, a 16:9 width:height aspect ratio would have a value of
|
||||
/// 16.0/9.0. If the maximum width is infinite, the initial width is determined
|
||||
/// by applying the aspect ratio to the maximum height.
|
||||
/// The [AspectRatio] widget uses a finite iterative process to compute the
|
||||
/// appropriate constraints for the child, and then lays the child out a single
|
||||
/// time with those constraints. This iterative process is efficient and does
|
||||
/// not require multiple layout passes.
|
||||
///
|
||||
/// The widget first tries the largest width permitted by the layout
|
||||
/// constraints, and determines the height of the widget by applying the given
|
||||
/// aspect ratio to the width, expressed as a ratio of width to height.
|
||||
///
|
||||
/// If the maximum width is infinite, the initial width is determined
|
||||
/// by applying the aspect ratio to the maximum height instead.
|
||||
///
|
||||
/// The widget then examines if the computed dimensions are compatible with the
|
||||
/// parent's constraints; if not, the dimensions are recomputed a second time,
|
||||
/// taking those constraints into account.
|
||||
///
|
||||
/// If the widget does not find a feasible size after consulting each
|
||||
/// constraint, the widget will eventually select a size for the child that
|
||||
/// meets the layout constraints but fails to meet the aspect ratio constraints.
|
||||
///
|
||||
/// {@tool dartpad}
|
||||
/// This examples shows how AspectRatio sets width when its parent's width
|
||||
/// constraint is infinite. Since its parent's allowed height is a fixed value,
|
||||
/// the actual width is determined via the given AspectRatio.
|
||||
/// This examples shows how [AspectRatio] sets the width when its parent's width
|
||||
/// constraint is infinite. Since the parent's allowed height is a fixed value,
|
||||
/// the actual width is determined via the given [aspectRatio].
|
||||
///
|
||||
/// Since the height is fixed at 100.0 in this example and the aspect ratio is
|
||||
/// set to 16 / 9, the width should then be 100.0 / 9 * 16.
|
||||
/// In this example, the height is fixed at 100.0 and the aspect ratio is set to
|
||||
/// 16 / 9, making the width 100.0 / 9 * 16.
|
||||
///
|
||||
/// ** See code in examples/api/lib/widgets/basic/aspect_ratio.0.dart **
|
||||
/// {@end-tool}
|
||||
///
|
||||
/// Now consider a second example, this time with an aspect ratio of 2.0 and
|
||||
/// layout constraints that require the width to be between 0.0 and 100.0 and
|
||||
/// the height to be between 0.0 and 100.0. We'll select a width of 100.0 (the
|
||||
/// biggest allowed) and a height of 50.0 (to match the aspect ratio).
|
||||
///
|
||||
/// {@tool dartpad}
|
||||
///
|
||||
/// This second example uses an aspect ratio of 2.0, and layout constraints that
|
||||
/// require the width to be between 0.0 and 100.0, and the height to be between
|
||||
/// 0.0 and 100.0. The widget selects a width of 100.0 (the biggest allowed) and
|
||||
/// a height of 50.0 (to match the aspect ratio).
|
||||
///
|
||||
/// ** See code in examples/api/lib/widgets/basic/aspect_ratio.1.dart **
|
||||
/// {@end-tool}
|
||||
///
|
||||
/// In that same situation, if the aspect ratio is 0.5, we'll also select a
|
||||
/// width of 100.0 (still the biggest allowed) and we'll attempt to use a height
|
||||
/// of 200.0. Unfortunately, that violates the constraints because the child can
|
||||
/// be at most 100.0 pixels tall. The widget will then take that value
|
||||
/// and apply the aspect ratio again to obtain a width of 50.0. That width is
|
||||
/// permitted by the constraints and the child receives a width of 50.0 and a
|
||||
/// height of 100.0. If the width were not permitted, the widget would
|
||||
/// continue iterating through the constraints. If the widget does not
|
||||
/// find a feasible size after consulting each constraint, the widget
|
||||
/// will eventually select a size for the child that meets the layout
|
||||
/// constraints but fails to meet the aspect ratio constraints.
|
||||
///
|
||||
/// {@tool dartpad}
|
||||
///
|
||||
/// This third example is similar to the second, but with the aspect ratio set
|
||||
/// to 0.5. The widget still selects a width of 100.0 (the biggest allowed), and
|
||||
/// attempts to use a height of 200.0. Unfortunately, that violates the
|
||||
/// constraints because the child can be at most 100.0 pixels tall. The widget
|
||||
/// will then take that value and apply the aspect ratio again to obtain a width
|
||||
/// of 50.0. That width is permitted by the constraints and the child receives a
|
||||
/// width of 50.0 and a height of 100.0. If the width were not permitted, the
|
||||
/// widget would continue iterating through the constraints.
|
||||
///
|
||||
/// ** See code in examples/api/lib/widgets/basic/aspect_ratio.2.dart **
|
||||
/// {@end-tool}
|
||||
///
|
||||
/// ## Setting the aspect ratio in unconstrained situations
|
||||
///
|
||||
/// When using a widget such as [FittedBox], the constraints are unbounded. This
|
||||
/// results in [AspectRatio] being unable to find a suitable set of constraints
|
||||
/// to apply. In that situation, consider explicitly setting a size using
|
||||
/// [SizedBox] instead of setting the aspect ratio using [AspectRatio]. The size
|
||||
/// is then scaled appropriately by the [FittedBox].
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [Align], a widget that aligns its child within itself and optionally
|
||||
|
@ -3531,6 +3553,8 @@ class Baseline extends SingleChildRenderObjectWidget {
|
|||
/// is a basic sliver that creates a bridge back to one of the usual box-based
|
||||
/// widgets.
|
||||
///
|
||||
/// _To learn more about slivers, see [CustomScrollView.slivers]._
|
||||
///
|
||||
/// Rather than using multiple [SliverToBoxAdapter] widgets to display multiple
|
||||
/// box widgets in a [CustomScrollView], consider using [SliverList],
|
||||
/// [SliverFixedExtentList], [SliverPrototypeExtentList], or [SliverGrid],
|
||||
|
@ -3569,6 +3593,7 @@ class SliverToBoxAdapter extends SingleChildRenderObjectWidget {
|
|||
/// See also:
|
||||
///
|
||||
/// * [CustomScrollView], which displays a scrollable list of slivers.
|
||||
/// * [Padding], the box version of this widget.
|
||||
class SliverPadding extends SingleChildRenderObjectWidget {
|
||||
/// Creates a sliver that applies padding on each side of another sliver.
|
||||
///
|
||||
|
@ -6640,6 +6665,7 @@ class RepaintBoundary extends SingleChildRenderObjectWidget {
|
|||
///
|
||||
/// * [AbsorbPointer], which also prevents its children from receiving pointer
|
||||
/// events but is itself visible to hit testing.
|
||||
/// * [SliverIgnorePointer], the sliver version of this widget.
|
||||
class IgnorePointer extends SingleChildRenderObjectWidget {
|
||||
/// Creates a widget that is invisible to hit testing.
|
||||
///
|
||||
|
|
|
@ -414,8 +414,8 @@ abstract class Widget extends DiagnosticableTree {
|
|||
///
|
||||
/// The [build] method of a stateless widget is typically only called in three
|
||||
/// situations: the first time the widget is inserted in the tree, when the
|
||||
/// widget's parent changes its configuration, and when an [InheritedWidget] it
|
||||
/// depends on changes.
|
||||
/// widget's parent changes its configuration (see [Element.rebuild]), and when
|
||||
/// an [InheritedWidget] it depends on changes.
|
||||
///
|
||||
/// If a widget's parent will regularly change the widget's configuration, or if
|
||||
/// it depends on inherited widgets that frequently change, then it is important
|
||||
|
@ -687,6 +687,9 @@ abstract class StatelessWidget extends Widget {
|
|||
///
|
||||
/// {@youtube 560 315 https://www.youtube.com/watch?v=IOyq-eTRhvo}
|
||||
///
|
||||
/// For more details on the mechanics of rebuilding a widget, see
|
||||
/// the discussion at [Element.rebuild].
|
||||
///
|
||||
/// {@tool snippet}
|
||||
///
|
||||
/// This is a skeleton of a stateful widget subclass called `YellowBird`.
|
||||
|
@ -869,7 +872,8 @@ const String _flutterWidgetsLibrary = 'package:flutter/widgets.dart';
|
|||
/// objects should override [didUpdateWidget] to respond to changes in their
|
||||
/// associated widget (e.g., to start implicit animations). The framework
|
||||
/// always calls [build] after calling [didUpdateWidget], which means any
|
||||
/// calls to [setState] in [didUpdateWidget] are redundant.
|
||||
/// calls to [setState] in [didUpdateWidget] are redundant. (See alse the
|
||||
/// discussion at [Element.rebuild].)
|
||||
/// * During development, if a hot reload occurs (whether initiated from the
|
||||
/// command line `flutter` tool by pressing `r`, or from an IDE), the
|
||||
/// [reassemble] method is called. This provides an opportunity to
|
||||
|
@ -1028,6 +1032,9 @@ abstract class State<T extends StatefulWidget> with Diagnosticable {
|
|||
///
|
||||
/// Implementations of this method should start with a call to the inherited
|
||||
/// method, as in `super.didUpdateWidget(oldWidget)`.
|
||||
///
|
||||
/// _See the discussion at [Element.rebuild] for more information on when this
|
||||
/// method is called._
|
||||
@mustCallSuper
|
||||
@protected
|
||||
void didUpdateWidget(covariant T oldWidget) { }
|
||||
|
@ -4671,6 +4678,103 @@ abstract class Element extends DiagnosticableTree implements BuildContext {
|
|||
/// The method will only rebuild if [dirty] is true. To rebuild regardless
|
||||
/// of the [dirty] flag, set `force` to true. Forcing a rebuild is convenient
|
||||
/// from [update], during which [dirty] is false.
|
||||
///
|
||||
/// ## When rebuilds happen
|
||||
///
|
||||
/// ### Terminology
|
||||
///
|
||||
/// [Widget]s represent the configuration of [Element]s. Each [Element] has a
|
||||
/// widget, specified in [Element.widget]. The term "widget" is often used
|
||||
/// when strictly speaking "element" would be more correct.
|
||||
///
|
||||
/// While an [Element] has a current [Widget], over time, that widget may be
|
||||
/// replaced by others. For example, the element backing a [ColoredBox] may
|
||||
/// first have as its widget a [ColoredBox] whose [ColoredBox.color] is blue,
|
||||
/// then later be given a new [ColoredBox] whose color is green.
|
||||
///
|
||||
/// At any particular time, multiple [Element]s in the same tree may have the
|
||||
/// same [Widget]. For example, the same [ColoredBox] with the green color may
|
||||
/// be used in multiple places in the widget tree at the same time, each being
|
||||
/// backed by a different [Element].
|
||||
///
|
||||
/// ### Marking an element dirty
|
||||
///
|
||||
/// An [Element] can be marked dirty between frames. This can happen for various
|
||||
/// reasons, including the following:
|
||||
///
|
||||
/// * The [State] of a [StatefulWidget] can cause its [Element] to be marked
|
||||
/// dirty by calling the [State.setState] method.
|
||||
///
|
||||
/// * When an [InheritedWidget] changes, descendants that have previously
|
||||
/// subscribed to it will be marked dirty.
|
||||
///
|
||||
/// * During a hot reload, every element is marked dirty (using [Element.reassemble]).
|
||||
///
|
||||
/// ### Rebuilding
|
||||
///
|
||||
/// Dirty elements are rebuilt during the next frame. Precisely how this is
|
||||
/// done depends on the kind of element. A [StatelessElement] rebuilds by
|
||||
/// using its widget's [StatelessWidget.build] method. A [StatefulElement]
|
||||
/// rebuilds by using its widget's state's [State.build] method. A
|
||||
/// [RenderObjectElement] rebuilds by updating its [RenderObject].
|
||||
///
|
||||
/// In many cases, the end result of rebuilding is a single child widget
|
||||
/// or (for [MultiChildRenderObjectElement]s) a list of children widgets.
|
||||
///
|
||||
/// These child widgets are used to update the [widget] property of the
|
||||
/// element's child (or children) elements. The new [Widget] is considered to
|
||||
/// correspond to an existing [Element] if it has the same [Type] and [Key].
|
||||
/// (In the case of [MultiChildRenderObjectElement]s, some effort is put into
|
||||
/// tracking widgets even when they change order; see
|
||||
/// [RenderObjectElement.updateChildren].)
|
||||
///
|
||||
/// If there was no corresponding previous child, this results in a new
|
||||
/// [Element] being created (using [Widget.createElement]); that element is
|
||||
/// then itself built, recursively.
|
||||
///
|
||||
/// If there was a child previously but the build did not provide a
|
||||
/// corresponding child to update it, then the old child is discarded (or, in
|
||||
/// cases involving [GlobalKey] reparenting, reused elsewhere in the element
|
||||
/// tree).
|
||||
///
|
||||
/// The most common case, however, is that there was a corresponding previous
|
||||
/// child. This is handled by asking the child [Element] to update itself
|
||||
/// using the new child [Widget]. In the case of [StatefulElement]s, this
|
||||
/// is what triggers [State.didUpdateWidget].
|
||||
///
|
||||
/// ### Not rebuilding
|
||||
///
|
||||
/// Before an [Element] is told to update itself with a new [Widget], the old
|
||||
/// and new objects are compared using `operator ==`.
|
||||
///
|
||||
/// In general, this is equivalent to doing a comparison using [identical] to
|
||||
/// see if the two objects are in fact the exact same instance. If they are,
|
||||
/// and if the element is not already marked dirty for other reasons, then the
|
||||
/// element skips updating itself as it can determine with certainty that
|
||||
/// there would be no value in updating itself or its descendants.
|
||||
///
|
||||
/// It is strongly advised to avoid overriding `operator ==` on [Widget]
|
||||
/// objects. While doing so seems like it could improve performance, in
|
||||
/// practice, for non-leaf widgets, it results in O(N²) behavior. This is
|
||||
/// because by necessity the comparison would have to include comparing child
|
||||
/// widgets, and if those child widgets also implement `operator ==`, it
|
||||
/// ultimately results in a complete walk of the widget tree... which is then
|
||||
/// repeated at each level of the tree. In practice, just rebuilding is
|
||||
/// cheaper. (Additionally, if _any_ subclass of [Widget] used in an
|
||||
/// application implements `operator ==`, then the compiler cannot inline the
|
||||
/// comparison anywhere, because it has to treat the call as virtual just in
|
||||
/// case the instance happens to be one that has an overriden operator.)
|
||||
///
|
||||
/// Instead, the best way to avoid unnecessary rebuilds is to cache the
|
||||
/// widgets that are returned from [State.build], so that each frame the same
|
||||
/// widgets are used until such time as they change. Several mechanisms exist
|
||||
/// to encourage this: `const` widgets, for example, are a form of automatic
|
||||
/// caching (if a widget is constructed using the `const` keyword, the same
|
||||
/// instance is returned each time it is constructed with the same arguments).
|
||||
///
|
||||
/// Another example is the [AnimatedBuilder.child] property, which allows the
|
||||
/// non-animating parts of a subtree to remain static even as the
|
||||
/// [AnimatedBuilder.builder] callback recreates the other components.
|
||||
@pragma('vm:prefer-inline')
|
||||
void rebuild({bool force = false}) {
|
||||
assert(_lifecycleState != _ElementLifecycle.initial);
|
||||
|
|
|
@ -281,17 +281,33 @@ typedef ImageErrorWidgetBuilder = Widget Function(
|
|||
/// ```
|
||||
/// {@end-tool}
|
||||
///
|
||||
/// ## Memory usage
|
||||
///
|
||||
/// The image is stored in memory in uncompressed form (so that it can be
|
||||
/// rendered). Large images will use a lot of memory: a 4K image (3840×2160)
|
||||
/// will use over 30MB of RAM (assuming 32 bits per pixel).
|
||||
///
|
||||
/// This problem is exacerbated by the images being cached in the [ImageCache],
|
||||
/// so large images can use memory for even longer than they are displayed.
|
||||
///
|
||||
/// The [Image.asset], [Image.network], [Image.file], and [Image.memory]
|
||||
/// constructors allow a custom decode size to be specified through
|
||||
/// `cacheWidth` and `cacheHeight` parameters. The engine will decode the
|
||||
/// image to the specified size, which is primarily intended to reduce the
|
||||
/// memory usage of [ImageCache].
|
||||
/// constructors allow a custom decode size to be specified through `cacheWidth`
|
||||
/// and `cacheHeight` parameters. The engine will then decode and store the
|
||||
/// image at the specified size, instead of the image's natural size.
|
||||
///
|
||||
/// This can significantly reduce the memory usage. For example, a 4K image that
|
||||
/// will be rendered at only 384×216 pixels (one-tenth the horizontal and
|
||||
/// vertical dimensions) would only use 330KB if those dimensions are specified
|
||||
/// using the `cacheWidth` and `cacheHeight` parameters, a 100-fold reduction in
|
||||
/// memory usage.
|
||||
///
|
||||
/// ### Web considerations
|
||||
///
|
||||
/// In the case where a network image is used on the Web platform, the
|
||||
/// `cacheWidth` and `cacheHeight` parameters are only supported when the application is
|
||||
/// running with the CanvasKit renderer. When the application is using the HTML renderer,
|
||||
/// the web engine delegates image decoding of network images to the Web, which does not support
|
||||
/// custom decode sizes.
|
||||
/// `cacheWidth` and `cacheHeight` parameters are only supported when the
|
||||
/// application is running with the CanvasKit renderer. When the application is
|
||||
/// using the HTML renderer, the web engine delegates image decoding of network
|
||||
/// images to the Web, which does not support custom decode sizes.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
|
@ -363,7 +379,7 @@ class Image extends StatefulWidget {
|
|||
///
|
||||
/// If [excludeFromSemantics] is true, then [semanticLabel] will be ignored.
|
||||
///
|
||||
/// If [cacheWidth] or [cacheHeight] are provided, it indicates to the
|
||||
/// If `cacheWidth` or `cacheHeight` are provided, they indicate to the
|
||||
/// engine that the image should be decoded at the specified size. The image
|
||||
/// will be rendered to the constraints of the layout or [width] and [height]
|
||||
/// regardless of these parameters. These parameters are primarily intended
|
||||
|
@ -372,9 +388,6 @@ class Image extends StatefulWidget {
|
|||
/// In the case where the network image is on the Web platform, the [cacheWidth]
|
||||
/// and [cacheHeight] parameters are ignored as the web engine delegates
|
||||
/// image decoding to the web which does not support custom decode sizes.
|
||||
//
|
||||
// TODO(garyq): We should eventually support custom decoding of network images
|
||||
// on Web as well, see https://github.com/flutter/flutter/issues/42789.
|
||||
Image.network(
|
||||
String src, {
|
||||
super.key,
|
||||
|
@ -420,7 +433,7 @@ class Image extends StatefulWidget {
|
|||
///
|
||||
/// If [excludeFromSemantics] is true, then [semanticLabel] will be ignored.
|
||||
///
|
||||
/// If [cacheWidth] or [cacheHeight] are provided, it indicates to the
|
||||
/// If `cacheWidth` or `cacheHeight` are provided, they indicate to the
|
||||
/// engine that the image must be decoded at the specified size. The image
|
||||
/// will be rendered to the constraints of the layout or [width] and [height]
|
||||
/// regardless of these parameters. These parameters are primarily intended
|
||||
|
@ -497,7 +510,7 @@ class Image extends StatefulWidget {
|
|||
///
|
||||
/// If [excludeFromSemantics] is true, then [semanticLabel] will be ignored.
|
||||
///
|
||||
/// If [cacheWidth] or [cacheHeight] are provided, it indicates to the
|
||||
/// If `cacheWidth` or `cacheHeight` are provided, they indicate to the
|
||||
/// engine that the image must be decoded at the specified size. The image
|
||||
/// will be rendered to the constraints of the layout or [width] and [height]
|
||||
/// regardless of these parameters. These parameters are primarily intended
|
||||
|
@ -655,7 +668,7 @@ class Image extends StatefulWidget {
|
|||
///
|
||||
/// If [excludeFromSemantics] is true, then [semanticLabel] will be ignored.
|
||||
///
|
||||
/// If [cacheWidth] or [cacheHeight] are provided, it indicates to the
|
||||
/// If `cacheWidth` or `cacheHeight` are provided, they indicate to the
|
||||
/// engine that the image must be decoded at the specified size. The image
|
||||
/// will be rendered to the constraints of the layout or [width] and [height]
|
||||
/// regardless of these parameters. These parameters are primarily intended
|
||||
|
|
|
@ -1681,7 +1681,7 @@ class _AnimatedSlideState extends ImplicitlyAnimatedWidgetState<AnimatedSlide> {
|
|||
/// * [AnimatedSwitcher], for fading between many children in sequence.
|
||||
/// * [FadeTransition], an explicitly animated version of this widget, where
|
||||
/// an [Animation] is provided by the caller instead of being built in.
|
||||
/// * [SliverAnimatedOpacity], for automatically transitioning a sliver's
|
||||
/// * [SliverAnimatedOpacity], for automatically transitioning a _sliver's_
|
||||
/// opacity over a given duration whenever the given opacity changes.
|
||||
class AnimatedOpacity extends ImplicitlyAnimatedWidget {
|
||||
/// Creates a widget that animates its opacity implicitly.
|
||||
|
|
|
@ -1108,6 +1108,23 @@ const TraversalEdgeBehavior kDefaultRouteTraversalEdgeBehavior = kIsWeb
|
|||
/// around in the overlay. Similarly, the navigator can be used to show a dialog
|
||||
/// by positioning the dialog widget above the current page.
|
||||
///
|
||||
/// ## Using the Pages API
|
||||
///
|
||||
/// The [Navigator] will convert its [Navigator.pages] into a stack of [Route]s
|
||||
/// if it is provided. A change in [Navigator.pages] will trigger an update to
|
||||
/// the stack of [Route]s. The [Navigator] will update its routes to match the
|
||||
/// new configuration of its [Navigator.pages]. To use this API, one can create
|
||||
/// a [Page] subclass and defines a list of [Page]s for [Navigator.pages]. A
|
||||
/// [Navigator.onPopPage] callback is also required to properly clean up the
|
||||
/// input pages in case of a pop.
|
||||
///
|
||||
/// By Default, the [Navigator] will use [DefaultTransitionDelegate] to decide
|
||||
/// how routes transition in or out of the screen. To customize it, define a
|
||||
/// [TransitionDelegate] subclass and provide it to the
|
||||
/// [Navigator.transitionDelegate].
|
||||
///
|
||||
/// For more information on using the pages API, see the [Router] widget.
|
||||
///
|
||||
/// ## Using the Navigator API
|
||||
///
|
||||
/// Mobile apps typically reveal their contents via full-screen elements
|
||||
|
@ -1127,21 +1144,6 @@ const TraversalEdgeBehavior kDefaultRouteTraversalEdgeBehavior = kIsWeb
|
|||
/// used in the [Scaffold.appBar] property) can automatically add a back
|
||||
/// button for user navigation.
|
||||
///
|
||||
/// ## Using the Pages API
|
||||
///
|
||||
/// The [Navigator] will convert its [Navigator.pages] into a stack of [Route]s
|
||||
/// if it is provided. A change in [Navigator.pages] will trigger an update to
|
||||
/// the stack of [Route]s. The [Navigator] will update its routes to match the
|
||||
/// new configuration of its [Navigator.pages]. To use this API, one can create
|
||||
/// a [Page] subclass and defines a list of [Page]s for [Navigator.pages]. A
|
||||
/// [Navigator.onPopPage] callback is also required to properly clean up the
|
||||
/// input pages in case of a pop.
|
||||
///
|
||||
/// By Default, the [Navigator] will use [DefaultTransitionDelegate] to decide
|
||||
/// how routes transition in or out of the screen. To customize it, define a
|
||||
/// [TransitionDelegate] subclass and provide it to the
|
||||
/// [Navigator.transitionDelegate].
|
||||
///
|
||||
/// ### Displaying a full-screen route
|
||||
///
|
||||
/// Although you can create a navigator directly, it's most common to use the
|
||||
|
@ -1364,6 +1366,14 @@ const TraversalEdgeBehavior kDefaultRouteTraversalEdgeBehavior = kIsWeb
|
|||
/// are created. The [Builder] widget can be used to access a [BuildContext] at
|
||||
/// a desired location in the widget subtree.
|
||||
///
|
||||
/// ### Finding the enclosing route
|
||||
///
|
||||
/// In the common case of a modal route, the enclosing route can be obtained
|
||||
/// from inside a build method using [ModalRoute.of]. To determine if the
|
||||
/// enclosing route is the active route (e.g. so that controls can be dimmed
|
||||
/// when the route is not active), the [Route.isCurrent] property can be checked
|
||||
/// on the returned route.
|
||||
///
|
||||
/// ## State Restoration
|
||||
///
|
||||
/// If provided with a [restorationScopeId] and when surrounded by a valid
|
||||
|
|
|
@ -139,7 +139,7 @@ class SafeArea extends StatelessWidget {
|
|||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [SafeArea], for insetting widgets to avoid operating system intrusions.
|
||||
/// * [SafeArea], for insetting box widgets to avoid operating system intrusions.
|
||||
/// * [SliverPadding], for insetting slivers in general.
|
||||
/// * [MediaQuery], from which the window padding is obtained.
|
||||
/// * [dart:ui.FlutterView.padding], which reports the padding from the operating
|
||||
|
|
|
@ -53,6 +53,8 @@ enum ScrollViewKeyboardDismissBehavior {
|
|||
/// [ScrollView] helps orchestrate these pieces by creating the [Scrollable] and
|
||||
/// the viewport and deferring to its subclass to create the slivers.
|
||||
///
|
||||
/// To learn more about slivers, see [CustomScrollView.slivers].
|
||||
///
|
||||
/// To control the initial scroll offset of the scroll view, provide a
|
||||
/// [controller] with its [ScrollController.initialScrollOffset] property set.
|
||||
///
|
||||
|
@ -345,6 +347,8 @@ abstract class ScrollView extends StatelessWidget {
|
|||
///
|
||||
/// Subclasses should override this method to build the slivers for the inside
|
||||
/// of the viewport.
|
||||
///
|
||||
/// To learn more about slivers, see [CustomScrollView.slivers].
|
||||
@protected
|
||||
List<Widget> buildSlivers(BuildContext context);
|
||||
|
||||
|
@ -461,7 +465,7 @@ abstract class ScrollView extends StatelessWidget {
|
|||
}
|
||||
}
|
||||
|
||||
/// A [ScrollView] that creates custom scroll effects using slivers.
|
||||
/// A [ScrollView] that creates custom scroll effects using [slivers].
|
||||
///
|
||||
/// A [CustomScrollView] lets you supply [slivers] directly to create various
|
||||
/// scrolling effects, such as lists, grids, and expanding headers. For example,
|
||||
|
@ -612,6 +616,101 @@ class CustomScrollView extends ScrollView {
|
|||
});
|
||||
|
||||
/// The slivers to place inside the viewport.
|
||||
///
|
||||
/// ## What is a sliver?
|
||||
///
|
||||
/// > _**sliver** (noun): a small, thin piece of something._
|
||||
///
|
||||
/// A _sliver_ is a widget backed by a [RenderSliver] subclass, i.e. one that
|
||||
/// implements the constraint/geometry protocol that uses [SliverConstraints]
|
||||
/// and [SliverGeometry].
|
||||
///
|
||||
/// This is as distinct from those widgets that are backed by [RenderBox]
|
||||
/// subclasses, which use [BoxConstraints] and [Size] respectively, and are
|
||||
/// known as box widgets. (Widgets like [Container], [Row], and [SizedBox] are
|
||||
/// box widgets.)
|
||||
///
|
||||
/// While boxes are much more straightforward (implementing a simple
|
||||
/// two-dimensional Cartesian layout system), slivers are much more powerful,
|
||||
/// and are optimized for one-axis scrolling environments.
|
||||
///
|
||||
/// Slivers are hosted in viewports, also known as scroll views, most notably
|
||||
/// [CustomScrollView].
|
||||
///
|
||||
/// ## Examples of slivers
|
||||
///
|
||||
/// The Flutter framework has many built-in sliver widgets, and custom widgets
|
||||
/// can be created in the same manner. By convention, sliver widgets always
|
||||
/// start with the prefix `Sliver` and are always used in properties called
|
||||
/// `sliver` or `slivers` (as opposed to `child` and `children` which are used
|
||||
/// for box widgets).
|
||||
///
|
||||
/// Examples of widgets unique to the sliver world include:
|
||||
///
|
||||
/// * [SliverList], a lazily-loading list of variably-sized box widgets.
|
||||
/// * [SliverFixedExtentList], a lazily-loading list of box widgets that are
|
||||
/// all forced to the same height.
|
||||
/// * [SliverPrototypeExtentList], a lazily-loading list of box widgets that
|
||||
/// are all forced to the same height as a given prototype widget.
|
||||
/// * [SliverGrid], a lazily-loading grid of box widgets.
|
||||
/// * [SliverAnimatedList] and [SliverAnimatedGrid], animated variants of
|
||||
/// [SliverList] and [SliverGrid].
|
||||
/// * [SliverFillRemaining], a widget that fills all remaining space in a
|
||||
/// scroll view, and lays a box widget out inside that space.
|
||||
/// * [SliverFillViewport], a widget that lays a list of boxes out, each
|
||||
/// being sized to fit the whole viewport.
|
||||
/// * [SliverPersistentHeader], a sliver that implements pinned and floating
|
||||
/// headers, e.g. used to implement [SliverAppBar].
|
||||
/// * [SliverToBoxAdapter], a sliver that wraps a box widget.
|
||||
///
|
||||
/// Examples of sliver variants of common box widgets include:
|
||||
///
|
||||
/// * [SliverOpacity], [SliverAnimatedOpacity], and [SliverFadeTransition],
|
||||
/// sliver versions of [Opacity], [AnimatedOpacity], and [FadeTransition].
|
||||
/// * [SliverIgnorePointer], a sliver version of [IgnorePointer].
|
||||
/// * [SliverLayoutBuilder], a sliver version of [LayoutBuilder].
|
||||
/// * [SliverOffstage], a sliver version of [Offstage].
|
||||
/// * [SliverPadding], a sliver version of [Padding].
|
||||
/// * [SliverReorderableList], a sliver version of [ReorderableList]
|
||||
/// * [SliverSafeArea], a sliver version of [SafeArea].
|
||||
/// * [SliverVisibility], a sliver version of [Visibility].
|
||||
///
|
||||
/// ## Benefits of slivers over boxes
|
||||
///
|
||||
/// The sliver protocol ([SliverConstraints] and [SliverGeometry]) enables
|
||||
/// _scroll effects_, such as floating app bars, widgets that expand and
|
||||
/// shrink during scroll, section headers that are pinned only while the
|
||||
/// section's children are visible, etc.
|
||||
///
|
||||
/// {@youtube 560 315 https://www.youtube.com/watch?v=Mz3kHQxBjGg}
|
||||
///
|
||||
/// ## Mixing slivers and boxes
|
||||
///
|
||||
/// In general, slivers always wrap box widgets to actually render anything
|
||||
/// (for example, there is no sliver equivalent of [Text] or [Container]);
|
||||
/// the sliver part of the equation is mostly about how these boxes should
|
||||
/// be laid out in a viewport (i.e. when scrolling).
|
||||
///
|
||||
/// Typically, the simplest way to combine boxes into a sliver environment is
|
||||
/// to use a [SliverList] (maybe using a [ListView, which is a convenient
|
||||
/// combination of a [CustomScrollView] and a [SliverList]). In rare cases,
|
||||
/// e.g. if a single [Divider] widget is needed between two [SliverGrid]s,
|
||||
/// a [SliverToBoxAdapter] can be used to wrap the box widgets.
|
||||
///
|
||||
/// ## Performance considerations
|
||||
///
|
||||
/// Because the purpose of scroll views is to, well, scroll, it is common
|
||||
/// for scroll views to contain more contents than are rendered on the screen
|
||||
/// at any particular time.
|
||||
///
|
||||
/// To improve the performance of scroll views, the content can be rendered in
|
||||
/// _lazy_ widgets, notably [SliverList] and [SliverGrid] (and their variants,
|
||||
/// such as [SliverFixedExtentList] and [SliverAnimatedGrid]). These widgets
|
||||
/// ensure that only the portion of their child lists that are actually
|
||||
/// visible get built, laid out, and painted.
|
||||
///
|
||||
/// The [ListView] and [GridView] widgets provide a convenient way to combine
|
||||
/// a [CustomScrollView] and a [SliverList] or [SliverGrid] (respectively).
|
||||
final List<Widget> slivers;
|
||||
|
||||
@override
|
||||
|
|
|
@ -976,6 +976,8 @@ abstract class SliverMultiBoxAdaptorWidget extends SliverWithKeepAliveWidget {
|
|||
/// A sliver that places multiple box children in a linear array along the main
|
||||
/// axis.
|
||||
///
|
||||
/// _To learn more about slivers, see [CustomScrollView.slivers]._
|
||||
///
|
||||
/// Each child is forced to have the [SliverConstraints.crossAxisExtent] in the
|
||||
/// cross axis but determines its own main axis extent.
|
||||
///
|
||||
|
@ -1071,8 +1073,8 @@ class SliverList extends SliverMultiBoxAdaptorWidget {
|
|||
addSemanticIndexes: addSemanticIndexes,
|
||||
));
|
||||
|
||||
/// A sliver that places multiple box children, separated by box widgets, in a linear array along the main
|
||||
/// axis.
|
||||
/// A sliver that places multiple box children, separated by box widgets, in a
|
||||
/// linear array along the main axis.
|
||||
///
|
||||
/// This constructor is appropriate for sliver lists with a large (or
|
||||
/// infinite) number of children because the builder is called only for those
|
||||
|
@ -1203,6 +1205,8 @@ class SliverList extends SliverMultiBoxAdaptorWidget {
|
|||
/// A sliver that places multiple box children with the same main axis extent in
|
||||
/// a linear array.
|
||||
///
|
||||
/// _To learn more about slivers, see [CustomScrollView.slivers]._
|
||||
///
|
||||
/// [SliverFixedExtentList] places its children in a linear array along the main
|
||||
/// axis starting at offset zero and without gaps. Each child is forced to have
|
||||
/// the [itemExtent] in the main axis and the
|
||||
|
@ -1380,6 +1384,8 @@ class SliverFixedExtentList extends SliverMultiBoxAdaptorWidget {
|
|||
|
||||
/// A sliver that places multiple box children in a two dimensional arrangement.
|
||||
///
|
||||
/// _To learn more about slivers, see [CustomScrollView.slivers]._
|
||||
///
|
||||
/// [SliverGrid] places its children in arbitrary positions determined by
|
||||
/// [gridDelegate]. Each child is forced to have the size specified by the
|
||||
/// [gridDelegate].
|
||||
|
@ -1961,7 +1967,7 @@ class SliverMultiBoxAdaptorElement extends RenderObjectElement implements Render
|
|||
/// See also:
|
||||
///
|
||||
/// * [Opacity], which can apply a uniform alpha effect to its child using the
|
||||
/// RenderBox layout protocol.
|
||||
/// [RenderBox] layout protocol.
|
||||
/// * [AnimatedOpacity], which uses an animation internally to efficiently
|
||||
/// animate [Opacity].
|
||||
/// * [SliverVisibility], which can hide a child more efficiently (albeit less
|
||||
|
@ -2041,6 +2047,10 @@ class SliverOpacity extends SingleChildRenderObjectWidget {
|
|||
/// When [ignoringSemantics] is true, the subtree will be invisible to
|
||||
/// the semantics layer (and thus e.g. accessibility tools). If
|
||||
/// [ignoringSemantics] is null, it uses the value of [ignoring].
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [IgnorePointer], the equivalent widget for boxes.
|
||||
class SliverIgnorePointer extends SingleChildRenderObjectWidget {
|
||||
/// Creates a sliver widget that is invisible to hit testing.
|
||||
///
|
||||
|
@ -2101,6 +2111,10 @@ class SliverIgnorePointer extends SingleChildRenderObjectWidget {
|
|||
/// To hide a sliver widget from view while it is
|
||||
/// not needed, prefer removing the widget from the tree entirely rather than
|
||||
/// keeping it alive in an [Offstage] subtree.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [Offstage], the equivalent widget for boxes.
|
||||
class SliverOffstage extends SingleChildRenderObjectWidget {
|
||||
/// Creates a sliver that visually hides its sliver child.
|
||||
const SliverOffstage({
|
||||
|
|
|
@ -10,6 +10,8 @@ import 'sliver.dart';
|
|||
|
||||
/// A sliver that contains multiple box children that each fills the viewport.
|
||||
///
|
||||
/// _To learn more about slivers, see [CustomScrollView.slivers]._
|
||||
///
|
||||
/// [SliverFillViewport] places its children in a linear array along the main
|
||||
/// axis. Each child is sized to fill the viewport, both in the main and cross
|
||||
/// axis.
|
||||
|
@ -163,6 +165,8 @@ class _RenderSliverFractionalPadding extends RenderSliverEdgeInsetsPadding {
|
|||
/// A sliver that contains a single box child that fills the remaining space in
|
||||
/// the viewport.
|
||||
///
|
||||
/// _To learn more about slivers, see [CustomScrollView.slivers]._
|
||||
///
|
||||
/// [SliverFillRemaining] will size its [child] to fill the viewport in the
|
||||
/// cross axis. The extent of the sliver and its child's size in the main axis
|
||||
/// is computed conditionally, described in further detail below.
|
||||
|
|
|
@ -114,6 +114,8 @@ abstract class SliverPersistentHeaderDelegate {
|
|||
///
|
||||
/// This is the layout primitive that [SliverAppBar] uses for its
|
||||
/// shrinking/growing effect.
|
||||
///
|
||||
/// _To learn more about slivers, see [CustomScrollView.slivers]._
|
||||
class SliverPersistentHeader extends StatelessWidget {
|
||||
/// Creates a sliver that varies its size when it is scrolled to the start of
|
||||
/// a viewport.
|
||||
|
|
|
@ -10,6 +10,8 @@ import 'sliver.dart';
|
|||
/// A sliver that places its box children in a linear array and constrains them
|
||||
/// to have the same extent as a prototype item along the main axis.
|
||||
///
|
||||
/// _To learn more about slivers, see [CustomScrollView.slivers]._
|
||||
///
|
||||
/// [SliverPrototypeExtentList] arranges its children in a line along
|
||||
/// the main axis starting at offset zero and without gaps. Each child is
|
||||
/// constrained to the same extent as the [prototypeItem] along the main axis
|
||||
|
@ -23,13 +25,12 @@ import 'sliver.dart';
|
|||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [SliverFixedExtentList], whose itemExtent is a pixel value.
|
||||
/// * [SliverFixedExtentList], whose children are forced to a given pixel
|
||||
/// extent.
|
||||
/// * [SliverList], which does not require its children to have the same
|
||||
/// extent in the main axis.
|
||||
/// * [SliverFillViewport], which sizes its children based on the
|
||||
/// size of the viewport, regardless of what else is in the scroll view.
|
||||
/// * [SliverList], which shows a list of variable-sized children in a
|
||||
/// viewport.
|
||||
class SliverPrototypeExtentList extends SliverMultiBoxAdaptorWidget {
|
||||
/// Creates a sliver that places its box children in a linear array and
|
||||
/// constrains them to have the same extent as a prototype item along
|
||||
|
|
|
@ -516,6 +516,7 @@ class SizeTransition extends AnimatedWidget {
|
|||
/// * [Opacity], which does not animate changes in opacity.
|
||||
/// * [AnimatedOpacity], which animates changes in opacity without taking an
|
||||
/// explicit [Animation] argument.
|
||||
/// * [SliverFadeTransition], the sliver version of this widget.
|
||||
class FadeTransition extends SingleChildRenderObjectWidget {
|
||||
/// Creates an opacity transition.
|
||||
///
|
||||
|
@ -586,6 +587,7 @@ class FadeTransition extends SingleChildRenderObjectWidget {
|
|||
/// See also:
|
||||
///
|
||||
/// * [SliverOpacity], which does not animate changes in opacity.
|
||||
/// * [FadeTransition], the box version of this widget.
|
||||
class SliverFadeTransition extends SingleChildRenderObjectWidget {
|
||||
/// Creates an opacity transition.
|
||||
///
|
||||
|
@ -995,16 +997,33 @@ class DefaultTextStyleTransition extends AnimatedWidget {
|
|||
/// they have identical implementations, if an [Animation] is being listened to,
|
||||
/// consider using an [AnimatedBuilder] instead for better readability.
|
||||
///
|
||||
/// {@tool dartpad}
|
||||
/// The following example uses a subclass of [ChangeNotifier] to hold the
|
||||
/// application model's state, in this case, a counter. A [ListenableBuilder] is
|
||||
/// then used to update the rendering (a [Text] widget) whenever the model changes.
|
||||
///
|
||||
/// ** See code in examples/api/lib/widgets/transitions/listenable_builder.2.dart **
|
||||
/// {@end-tool}
|
||||
///
|
||||
/// {@tool dartpad}
|
||||
/// This version is identical, but using a [ValueNotifier] instead of a
|
||||
/// dedicated subclass of [ChangeNotifier]. This works well when there is only a
|
||||
/// single immutable value to be tracked.
|
||||
///
|
||||
/// ** See code in examples/api/lib/widgets/transitions/listenable_builder.1.dart **
|
||||
/// {@end-tool}
|
||||
///
|
||||
/// ## Performance optimizations
|
||||
///
|
||||
/// {@template flutter.widgets.transitions.ListenableBuilder.optimizations}
|
||||
/// If the [builder] function contains a subtree that does not depend on the
|
||||
/// [listenable], it's often more efficient to build that subtree once instead
|
||||
/// of rebuilding it on every change of the listenable.
|
||||
/// [listenable], it is more efficient to build that subtree once instead
|
||||
/// of rebuilding it on every change of the [listenable].
|
||||
///
|
||||
/// If a pre-built subtree is passed as the [child] parameter, the
|
||||
/// [ListenableBuilder] will pass it back to the [builder] function so that it
|
||||
/// can be incorporated into the build.
|
||||
/// Performance is therefore improved by specifying any widgets that don't need
|
||||
/// to change using the prebuilt [child] attribute. The [ListenableBuilder]
|
||||
/// passes this [child] back to the [builder] callback so that it can be
|
||||
/// incorporated into the build.
|
||||
///
|
||||
/// Using this pre-built [child] is entirely optional, but can improve
|
||||
/// performance significantly in some cases and is therefore a good practice.
|
||||
|
@ -1013,32 +1032,19 @@ class DefaultTextStyleTransition extends AnimatedWidget {
|
|||
/// {@tool dartpad}
|
||||
/// This example shows how a [ListenableBuilder] can be used to listen to a
|
||||
/// [FocusNode] (which is also a [ChangeNotifier]) to see when a subtree has
|
||||
/// focus, and modify a decoration when its focus state changes.
|
||||
/// focus, and modify a decoration when its focus state changes. Only the
|
||||
/// [Container] is rebuilt when the [FocusNode] changes; the rest of the tree
|
||||
/// (notably the [Focus] widget) remain unchanged from frame to frame.
|
||||
///
|
||||
/// ** See code in examples/api/lib/widgets/transitions/listenable_builder.0.dart **
|
||||
/// {@end-tool}
|
||||
///
|
||||
/// {@template flutter.flutter.ListenableBuilder.ChangeNotifier.rebuild}
|
||||
/// ## Improve rebuild performance
|
||||
///
|
||||
/// Performance can be improved by specifying any widgets that don't need to
|
||||
/// change as a result of changes in the listener as the prebuilt
|
||||
/// [ListenableBuilder.child] attribute.
|
||||
///
|
||||
/// {@tool dartpad}
|
||||
/// The following example implements a simple counter that utilizes a
|
||||
/// [ListenableBuilder] to limit rebuilds to only the [Text] widget containing
|
||||
/// the count. The current count is stored in a [ValueNotifier], which rebuilds
|
||||
/// the [ListenableBuilder]'s contents when its value is changed.
|
||||
///
|
||||
/// ** See code in examples/api/lib/widgets/transitions/listenable_builder.1.dart **
|
||||
/// {@end-tool}
|
||||
/// {@endtemplate}
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [AnimatedBuilder], which has the same functionality, but is named more
|
||||
/// appropriately for a builder triggered by [Animation]s.
|
||||
/// * [ValueListenableBuilder], which is specialized for [ValueNotifier]s and
|
||||
/// reports the new value in its builder callback.
|
||||
class ListenableBuilder extends AnimatedWidget {
|
||||
/// Creates a builder that responds to changes in [listenable].
|
||||
///
|
||||
|
@ -1050,17 +1056,23 @@ class ListenableBuilder extends AnimatedWidget {
|
|||
this.child,
|
||||
});
|
||||
|
||||
// Overridden getter to replace with documentation tailored to
|
||||
// ListenableBuilder.
|
||||
|
||||
/// The [Listenable] supplied to the constructor.
|
||||
///
|
||||
/// Also accessible through the [listenable] getter.
|
||||
/// {@tool dartpad}
|
||||
/// In this example, the [listenable] is a [ChangeNotifier] subclass that
|
||||
/// encapsulates a list. The [ListenableBuilder] is rebuilt each time an item
|
||||
/// is added to the list.
|
||||
///
|
||||
/// ** See code in examples/api/lib/widgets/transitions/listenable_builder.3.dart **
|
||||
/// {@end-tool}
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [AnimatedBuilder], a widget with an identical functionality commonly
|
||||
/// * [AnimatedBuilder], a widget with identical functionality commonly
|
||||
/// used with [Animation] [Listenable]s for better readability.
|
||||
//
|
||||
// Overridden getter to replace with documentation tailored to
|
||||
// ListenableBuilder.
|
||||
@override
|
||||
Listenable get listenable => super.listenable;
|
||||
|
||||
|
@ -1090,6 +1102,12 @@ class ListenableBuilder extends AnimatedWidget {
|
|||
///
|
||||
/// {@youtube 560 315 https://www.youtube.com/watch?v=N-RiyZlv8v8}
|
||||
///
|
||||
/// Despite the name, [AnimatedBuilder] is not limited to [Animation]s, any
|
||||
/// subtype of [Listenable] (such as [ChangeNotifier] or [ValueNotifier]) can be
|
||||
/// used to trigger rebuilds. Although they have identical implementations, if
|
||||
/// an [Animation] is not being listened to, consider using a
|
||||
/// [ListenableBuilder] for better readability.
|
||||
///
|
||||
/// ## Performance optimizations
|
||||
///
|
||||
/// {@template flutter.widgets.transitions.AnimatedBuilder.optimizations}
|
||||
|
@ -1113,31 +1131,9 @@ class ListenableBuilder extends AnimatedWidget {
|
|||
/// ** See code in examples/api/lib/widgets/transitions/animated_builder.0.dart **
|
||||
/// {@end-tool}
|
||||
///
|
||||
/// ## Improve rebuild performance
|
||||
///
|
||||
/// Despite the name, [AnimatedBuilder] is not limited to [Animation]s, any
|
||||
/// subtype of [Listenable] (such as [ChangeNotifier] or [ValueNotifier]) can be
|
||||
/// used to trigger rebuilds. Although they have identical implementations, if
|
||||
/// an [Animation] is not being listened to, consider using a
|
||||
/// [ListenableBuilder] for better readability.
|
||||
///
|
||||
/// You can use an [AnimatedBuilder] or [ListenableBuilder] to rebuild only
|
||||
/// certain parts of a widget when the [Listenable] notifies its listeners. You
|
||||
/// can improve performance by specifying any widgets that don't need to change
|
||||
/// as a result of changes in the listener as the prebuilt [child] attribute.
|
||||
///
|
||||
/// {@tool dartpad}
|
||||
/// The following example implements a simple counter that utilizes an
|
||||
/// [AnimatedBuilder] to limit rebuilds to only the [Text] widget. The current
|
||||
/// count is stored in a [ValueNotifier], which rebuilds the [AnimatedBuilder]'s
|
||||
/// contents when its value is changed.
|
||||
///
|
||||
/// ** See code in examples/api/lib/widgets/transitions/listenable_builder.1.dart **
|
||||
/// {@end-tool}
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [ListenableBuilder], a widget with similar functionality, but is named
|
||||
/// * [ListenableBuilder], a widget with similar functionality, but named
|
||||
/// more appropriately for a builder triggered on changes in [Listenable]s
|
||||
/// that aren't [Animation]s.
|
||||
/// * [TweenAnimationBuilder], which animates a property to a target value
|
||||
|
@ -1164,13 +1160,27 @@ class AnimatedBuilder extends ListenableBuilder {
|
|||
/// when the [animation] isn't an [Animation].
|
||||
Listenable get animation => super.listenable;
|
||||
|
||||
/// The [Listenable] supplied to the constructor (typically an [Animation]).
|
||||
///
|
||||
/// Also accessible through the [animation] getter.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [ListenableBuilder], a widget with identical functionality commonly
|
||||
/// used with non-animation [Listenable]s for readability.
|
||||
//
|
||||
// Overridden getter to replace with documentation tailored to
|
||||
// AnimatedBuilder.
|
||||
// ListenableBuilder.
|
||||
@override
|
||||
Listenable get listenable => super.listenable;
|
||||
|
||||
/// Called every time the [animation] notifies about a change.
|
||||
///
|
||||
/// The child given to the builder should typically be part of the returned
|
||||
/// widget tree.
|
||||
//
|
||||
// Overridden getter to replace with documentation tailored to
|
||||
// AnimatedBuilder.
|
||||
@override
|
||||
TransitionBuilder get builder => super.builder;
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ import 'ticker_provider.dart';
|
|||
/// * [AnimatedSwitcher], which can fade from one child to the next as the
|
||||
/// subtree changes.
|
||||
/// * [AnimatedCrossFade], which can fade between two specific children.
|
||||
/// * [SliverVisibility], the sliver equivalent of this widget.
|
||||
class Visibility extends StatelessWidget {
|
||||
/// Control whether the given [child] is [visible].
|
||||
///
|
||||
|
@ -291,9 +292,14 @@ class Visibility extends StatelessWidget {
|
|||
/// sliver child.
|
||||
///
|
||||
/// Using this widget is not necessary to hide children. The simplest way to
|
||||
/// hide a child is just to not include it, or, if a child _must_ be given (e.g.
|
||||
/// because the parent is a [StatelessWidget]) then to use a childless
|
||||
/// [SliverToBoxAdapter] instead of the child that would otherwise be included.
|
||||
/// hide a child is just to not include it. If a child _must_ be given (e.g.
|
||||
/// because the parent is a [StatelessWidget]), then including a childless
|
||||
/// [SliverToBoxAdapter] instead of the child that would otherwise be included
|
||||
/// is typically more efficient than using [SliverVisibility].
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [Visibility], the equivalent widget for boxes.
|
||||
class SliverVisibility extends StatelessWidget {
|
||||
/// Control whether the given [sliver] is [visible].
|
||||
///
|
||||
|
|
Loading…
Reference in a new issue