Documentation improvements (#122787)

Documentation improvements
This commit is contained in:
Ian Hickson 2023-03-22 11:58:57 -07:00 committed by GitHub
parent 98a3055010
commit 3fe5740153
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
30 changed files with 730 additions and 211 deletions

View file

@ -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),
),
),
);
}
}

View file

@ -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}');
},
),
],
),
);
}
}

View file

@ -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,
);
},
),
),
],
),
);
}
}

View file

@ -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);

View file

@ -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) {

View file

@ -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;
}

View file

@ -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].

View file

@ -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;

View file

@ -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.

View file

@ -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;

View file

@ -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.
///

View file

@ -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

View file

@ -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;

View file

@ -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();

View file

@ -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

View file

@ -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)) {

View file

@ -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].

View file

@ -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.
///

View file

@ -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);

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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({

View file

@ -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.

View file

@ -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.

View file

@ -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

View file

@ -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;
}

View file

@ -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].
///