diff --git a/packages/flutter/lib/src/widgets/page_view.dart b/packages/flutter/lib/src/widgets/page_view.dart index bb61340219..285879a221 100644 --- a/packages/flutter/lib/src/widgets/page_view.dart +++ b/packages/flutter/lib/src/widgets/page_view.dart @@ -562,6 +562,10 @@ class PageView extends StatefulWidget { /// /// [itemBuilder] will be called only with indices greater than or equal to /// zero and less than [itemCount]. + /// + /// [PageView.builder] by default does not support child reordering. If + /// you are planning to change child order at a later time, consider using + /// [PageView] or [PageView.custom]. PageView.builder({ Key key, this.scrollDirection = Axis.horizontal, @@ -579,6 +583,84 @@ class PageView extends StatefulWidget { /// Creates a scrollable list that works page by page with a custom child /// model. + /// + /// {@tool sample} + /// + /// This [PageView] uses a custom [SliverChildBuilderDelegate] to support child + /// reordering. + /// + /// ```dart + /// class MyPageView extends StatefulWidget { + /// @override + /// _MyPageViewState createState() => _MyPageViewState(); + /// } + /// + /// class _MyPageViewState extends State { + /// List items = ['1', '2', '3', '4', '5']; + /// + /// void _reverse() { + /// setState(() { + /// items = items.reversed.toList(); + /// }); + /// } + /// + /// @override + /// Widget build(BuildContext context) { + /// return Scaffold( + /// body: SafeArea( + /// child: PageView.custom( + /// childrenDelegate: SliverChildBuilderDelegate( + /// (BuildContext context, int index) { + /// return KeepAlive( + /// data: items[index], + /// key: ValueKey(items[index]), + /// ); + /// }, + /// childCount: items.length, + /// findChildIndexCallback: (Key key) { + /// final ValueKey valueKey = key; + /// final String data = valueKey.value; + /// return items.indexOf(data); + /// } + /// ), + /// ), + /// ), + /// bottomNavigationBar: BottomAppBar( + /// child: Row( + /// mainAxisAlignment: MainAxisAlignment.center, + /// children: [ + /// FlatButton( + /// onPressed: () => _reverse(), + /// child: Text('Reverse items'), + /// ), + /// ], + /// ), + /// ), + /// ); + /// } + /// } + /// + /// class KeepAlive extends StatefulWidget { + /// const KeepAlive({Key key, this.data}) : super(key: key); + /// + /// final String data; + /// + /// @override + /// _KeepAliveState createState() => _KeepAliveState(); + /// } + /// + /// class _KeepAliveState extends State with AutomaticKeepAliveClientMixin{ + /// @override + /// bool get wantKeepAlive => true; + /// + /// @override + /// Widget build(BuildContext context) { + /// super.build(context); + /// return Text(widget.data); + /// } + /// } + /// ``` + /// {@end-tool} PageView.custom({ Key key, this.scrollDirection = Axis.horizontal, diff --git a/packages/flutter/lib/src/widgets/scroll_view.dart b/packages/flutter/lib/src/widgets/scroll_view.dart index 2ab40d53b9..c1b2897372 100644 --- a/packages/flutter/lib/src/widgets/scroll_view.dart +++ b/packages/flutter/lib/src/widgets/scroll_view.dart @@ -917,6 +917,10 @@ class ListView extends BoxScrollView { /// `addSemanticIndexes` argument corresponds to the /// [SliverChildBuilderDelegate.addSemanticIndexes] property. None may be /// null. + /// + /// [ListView.builder] by default does not support child reordering. If + /// you are planning to change child order at a later time, consider using + /// [ListView] or [ListView.custom]. ListView.builder({ Key key, Axis scrollDirection = Axis.vertical, @@ -1065,6 +1069,84 @@ class ListView extends BoxScrollView { /// /// For example, a custom child model can control the algorithm used to /// estimate the size of children that are not actually visible. + /// + /// {@tool sample} + /// + /// This [ListView] uses a custom [SliverChildBuilderDelegate] to support child + /// reordering. + /// + /// ```dart + /// class MyListView extends StatefulWidget { + /// @override + /// _MyListViewState createState() => _MyListViewState(); + /// } + /// + /// class _MyListViewState extends State { + /// List items = ['1', '2', '3', '4', '5']; + /// + /// void _reverse() { + /// setState(() { + /// items = items.reversed.toList(); + /// }); + /// } + /// + /// @override + /// Widget build(BuildContext context) { + /// return Scaffold( + /// body: SafeArea( + /// child: ListView.custom( + /// childrenDelegate: SliverChildBuilderDelegate( + /// (BuildContext context, int index) { + /// return KeepAlive( + /// data: items[index], + /// key: ValueKey(items[index]), + /// ); + /// }, + /// childCount: items.length, + /// findChildIndexCallback: (Key key) { + /// final ValueKey valueKey = key; + /// final String data = valueKey.value; + /// return items.indexOf(data); + /// } + /// ), + /// ), + /// ), + /// bottomNavigationBar: BottomAppBar( + /// child: Row( + /// mainAxisAlignment: MainAxisAlignment.center, + /// children: [ + /// FlatButton( + /// onPressed: () => _reverse(), + /// child: Text('Reverse items'), + /// ), + /// ], + /// ), + /// ), + /// ); + /// } + /// } + /// + /// class KeepAlive extends StatefulWidget { + /// const KeepAlive({Key key, this.data}) : super(key: key); + /// + /// final String data; + /// + /// @override + /// _KeepAliveState createState() => _KeepAliveState(); + /// } + /// + /// class _KeepAliveState extends State with AutomaticKeepAliveClientMixin{ + /// @override + /// bool get wantKeepAlive => true; + /// + /// @override + /// Widget build(BuildContext context) { + /// super.build(context); + /// return Text(widget.data); + /// } + /// } + /// ``` + /// {@end-tool} const ListView.custom({ Key key, Axis scrollDirection = Axis.vertical,