From e65c37ee45d8dfe19ea64da159cc0e5f1e07ae9d Mon Sep 17 00:00:00 2001 From: Ian Hickson Date: Tue, 8 Aug 2023 15:08:32 -0700 Subject: [PATCH] More PageStorage clarity in the documentation (#131954) Fixes https://github.com/flutter/flutter/issues/10867 --- .../lib/src/material/expansion_tile.dart | 6 ++-- .../src/material/paginated_data_table.dart | 3 ++ .../flutter/lib/src/widgets/page_storage.dart | 28 ++++++++++--------- .../flutter/lib/src/widgets/page_view.dart | 8 ++++++ .../lib/src/widgets/scroll_position.dart | 2 -- .../flutter/lib/src/widgets/scroll_view.dart | 16 +++++++++++ .../flutter/lib/src/widgets/scrollable.dart | 8 ++++++ .../src/widgets/single_child_scroll_view.dart | 2 ++ 8 files changed, 55 insertions(+), 18 deletions(-) diff --git a/packages/flutter/lib/src/material/expansion_tile.dart b/packages/flutter/lib/src/material/expansion_tile.dart index 3dc8e99f8647b..bf865d39f4360 100644 --- a/packages/flutter/lib/src/material/expansion_tile.dart +++ b/packages/flutter/lib/src/material/expansion_tile.dart @@ -184,9 +184,9 @@ class ExpansionTileController { /// A single-line [ListTile] with an expansion arrow icon that expands or collapses /// the tile to reveal or hide the [children]. /// -/// This widget is typically used with [ListView] to create an -/// "expand / collapse" list entry. When used with scrolling widgets like -/// [ListView], a unique [PageStorageKey] must be specified to enable the +/// This widget is typically used with [ListView] to create an "expand / +/// collapse" list entry. When used with scrolling widgets like [ListView], a +/// unique [PageStorageKey] must be specified as the [key], to enable the /// [ExpansionTile] to save and restore its expanded state when it is scrolled /// in and out of view. /// diff --git a/packages/flutter/lib/src/material/paginated_data_table.dart b/packages/flutter/lib/src/material/paginated_data_table.dart index 3c5fcdf5381dc..ef85796455910 100644 --- a/packages/flutter/lib/src/material/paginated_data_table.dart +++ b/packages/flutter/lib/src/material/paginated_data_table.dart @@ -28,6 +28,9 @@ import 'theme.dart'; /// Data is read lazily from a [DataTableSource]. The widget is presented /// as a [Card]. /// +/// If the [key] is a [PageStorageKey], the [initialFirstRowIndex] is persisted +/// to [PageStorage]. +/// /// See also: /// /// * [DataTable], which is not paginated. diff --git a/packages/flutter/lib/src/widgets/page_storage.dart b/packages/flutter/lib/src/widgets/page_storage.dart index 1cedea07b1419..0a0da4e4103ba 100644 --- a/packages/flutter/lib/src/widgets/page_storage.dart +++ b/packages/flutter/lib/src/widgets/page_storage.dart @@ -9,17 +9,19 @@ import 'framework.dart'; // Examples can assume: // late BuildContext context; -/// A key can be used to persist the widget state in storage after -/// the destruction and will be restored when recreated. +/// A [Key] that can be used to persist the widget state in storage after the +/// destruction and will be restored when recreated. /// -/// Each key with its value plus the ancestor chain of other PageStorageKeys need to -/// be unique within the widget's closest ancestor [PageStorage]. To make it possible for a -/// saved value to be found when a widget is recreated, the key's value must -/// not be objects whose identity will change each time the widget is created. +/// Each key with its value plus the ancestor chain of other [PageStorageKey]s +/// need to be unique within the widget's closest ancestor [PageStorage]. To +/// make it possible for a saved value to be found when a widget is recreated, +/// the key's value must not be objects whose identity will change each time the +/// widget is created. /// /// See also: /// -/// * [PageStorage], which is the closet ancestor for [PageStorageKey]. +/// * [PageStorage], which manages the data storage for widgets using +/// [PageStorageKey]s. class PageStorageKey extends ValueKey { /// Creates a [ValueKey] that defines where [PageStorage] values will be saved. const PageStorageKey(super.value); @@ -136,12 +138,12 @@ class PageStorageBucket { /// included in routes. /// /// [PageStorageKey] is used by [Scrollable] if [ScrollController.keepScrollOffset] -/// is enabled to save their [ScrollPosition]s. When more than one -/// scrollable ([ListView], [SingleChildScrollView], [TextField], etc.) appears -/// within the widget's closest ancestor [PageStorage] (such as within the same route), -/// if you want to save all of their positions independently, -/// you should give each of them unique [PageStorageKey]s, or set some of their -/// `keepScrollOffset` false to prevent saving. +/// is enabled to save their [ScrollPosition]s. When more than one scrollable +/// ([ListView], [SingleChildScrollView], [TextField], etc.) appears within the +/// widget's closest ancestor [PageStorage] (such as within the same route), to +/// save all of their positions independently, one must give each of them unique +/// [PageStorageKey]s, or set the `keepScrollOffset` property of some such +/// widgets to false to prevent saving. /// /// {@tool dartpad} /// This sample shows how to explicitly use a [PageStorage] to diff --git a/packages/flutter/lib/src/widgets/page_view.dart b/packages/flutter/lib/src/widgets/page_view.dart index 9660ddefb3dbe..5d75be724366e 100644 --- a/packages/flutter/lib/src/widgets/page_view.dart +++ b/packages/flutter/lib/src/widgets/page_view.dart @@ -612,6 +612,14 @@ const PageScrollPhysics _kPagePhysics = PageScrollPhysics(); /// ** See code in examples/api/lib/widgets/page_view/page_view.0.dart ** /// {@end-tool} /// +/// ## Persisting the scroll position during a session +/// +/// Scroll views attempt to persist their scroll position using [PageStorage]. +/// For a [PageView], this can be disabled by setting [PageController.keepPage] +/// to false on the [controller]. If it is enabled, using a [PageStorageKey] for +/// the [key] of this widget is recommended to help disambiguate different +/// scroll views from each other. +/// /// See also: /// /// * [PageController], which controls which page is visible in the view. diff --git a/packages/flutter/lib/src/widgets/scroll_position.dart b/packages/flutter/lib/src/widgets/scroll_position.dart index e9154a1218afb..6311b1aae493c 100644 --- a/packages/flutter/lib/src/widgets/scroll_position.dart +++ b/packages/flutter/lib/src/widgets/scroll_position.dart @@ -178,8 +178,6 @@ enum ScrollPositionAlignmentPolicy { abstract class ScrollPosition extends ViewportOffset with ScrollMetrics { /// Creates an object that determines which portion of the content is visible /// in a scroll view. - /// - /// The [physics], [context], and [keepScrollOffset] parameters must not be null. ScrollPosition({ required this.physics, required this.context, diff --git a/packages/flutter/lib/src/widgets/scroll_view.dart b/packages/flutter/lib/src/widgets/scroll_view.dart index 33708cc11d648..47a1bddc3ab08 100644 --- a/packages/flutter/lib/src/widgets/scroll_view.dart +++ b/packages/flutter/lib/src/widgets/scroll_view.dart @@ -61,6 +61,16 @@ enum ScrollViewKeyboardDismissBehavior { /// To control the initial scroll offset of the scroll view, provide a /// [controller] with its [ScrollController.initialScrollOffset] property set. /// +/// {@template flutter.widgets.ScrollView.PageStorage} +/// ## Persisting the scroll position during a session +/// +/// Scroll views attempt to persist their scroll position using [PageStorage]. +/// This can be disabled by setting [ScrollController.keepScrollOffset] to false +/// on the [controller]. If it is enabled, using a [PageStorageKey] for the +/// [key] of this widget is recommended to help disambiguate different scroll +/// views from each other. +/// {@endtemplate} +/// /// See also: /// /// * [ListView], which is a commonly used [ScrollView] that displays a @@ -619,6 +629,8 @@ abstract class ScrollView extends StatelessWidget { /// parameter `semanticChildCount`. This should always be the same as the /// number of widgets wrapped in [IndexedSemantics]. /// +/// {@macro flutter.widgets.ScrollView.PageStorage} +/// /// See also: /// /// * [SliverList], which is a sliver that displays linear list of children. @@ -1165,6 +1177,8 @@ abstract class BoxScrollView extends ScrollView { /// /// {@macro flutter.widgets.BoxScroll.scrollBehaviour} /// +/// {@macro flutter.widgets.ScrollView.PageStorage} +/// /// See also: /// /// * [SingleChildScrollView], which is a scrollable widget that has a single @@ -1810,6 +1824,8 @@ class ListView extends BoxScrollView { /// ** See code in examples/api/lib/widgets/scroll_view/list_view.0.dart ** /// {@end-tool} /// +/// {@macro flutter.widgets.ScrollView.PageStorage} +/// /// See also: /// /// * [SingleChildScrollView], which is a scrollable widget that has a single diff --git a/packages/flutter/lib/src/widgets/scrollable.dart b/packages/flutter/lib/src/widgets/scrollable.dart index 17a90007d42bb..1331de1d57de0 100644 --- a/packages/flutter/lib/src/widgets/scrollable.dart +++ b/packages/flutter/lib/src/widgets/scrollable.dart @@ -72,6 +72,14 @@ typedef TwoDimensionalViewportBuilder = Widget Function(BuildContext context, Vi /// [PageController], which creates a page-oriented scroll position subclass /// that keeps the same page visible when the [Scrollable] resizes. /// +/// ## Persisting the scroll position during a session +/// +/// Scrollables attempt to persist their scroll position using [PageStorage]. +/// This can be disabled by setting [ScrollController.keepScrollOffset] to false +/// on the [controller]. If it is enabled, using a [PageStorageKey] for the +/// [key] of this widget (or one of its ancestors, e.g. a [ScrollView]) is +/// recommended to help disambiguate different [Scrollable]s from each other. +/// /// See also: /// /// * [ListView], which is a commonly used [ScrollView] that displays a diff --git a/packages/flutter/lib/src/widgets/single_child_scroll_view.dart b/packages/flutter/lib/src/widgets/single_child_scroll_view.dart index 818a8a1ad4487..3255c328eb641 100644 --- a/packages/flutter/lib/src/widgets/single_child_scroll_view.dart +++ b/packages/flutter/lib/src/widgets/single_child_scroll_view.dart @@ -130,6 +130,8 @@ import 'scrollable.dart'; /// ** See code in examples/api/lib/widgets/single_child_scroll_view/single_child_scroll_view.1.dart ** /// {@end-tool} /// +/// {@macro flutter.widgets.ScrollView.PageStorage} +/// /// See also: /// /// * [ListView], which handles multiple children in a scrolling list.