Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
1ec625ff
Commit
1ec625ff
authored
Feb 08, 2017
by
Adam Barth
Committed by
GitHub
Feb 08, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Remove PageableList (#7997)
All clients have moved to PageView.
parent
b4ec00c2
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
23 additions
and
732 deletions
+23
-732
item.dart
examples/flutter_gallery/lib/gallery/item.dart
+1
-1
tabs.dart
packages/flutter/lib/src/material/tabs.dart
+3
-3
pageable_list.dart
packages/flutter/lib/src/widgets/pageable_list.dart
+0
-591
scrollable.dart
packages/flutter/lib/src/widgets/scrollable.dart
+0
-1
virtual_viewport.dart
packages/flutter/lib/src/widgets/virtual_viewport.dart
+1
-1
widgets.dart
packages/flutter/lib/widgets.dart
+0
-1
pageable_list_test.dart
packages/flutter/test/widgets/pageable_list_test.dart
+18
-134
No files found.
examples/flutter_gallery/lib/gallery/item.dart
View file @
1ec625ff
...
...
@@ -170,7 +170,7 @@ final List<GalleryItem> kAllGalleryItems = <GalleryItem>[
),
new
GalleryItem
(
title:
'Page selector'
,
subtitle:
'Page
able list
with indicator'
,
subtitle:
'Page
View
with indicator'
,
routeName:
PageSelectorDemo
.
routeName
,
buildRoute:
(
BuildContext
context
)
=>
new
PageSelectorDemo
()
),
...
...
packages/flutter/lib/src/material/tabs.dart
View file @
1ec625ff
...
...
@@ -590,13 +590,13 @@ class _TabBarState extends State<TabBar> {
}
}
/// A page
able list
that displays the widget which corresponds to the currently
/// A page
view
that displays the widget which corresponds to the currently
/// selected tab. Typically used in conjuction with a [TabBar].
///
/// If a [TabController] is not provided, then there must be a [DefaultTabController]
/// ancestor.
class
TabBarView
extends
StatefulWidget
{
/// Creates a page
able list
with one child per tab.
/// Creates a page
view
with one child per tab.
///
/// The length of [children] must be the same as the [controller]'s length.
TabBarView
({
...
...
@@ -744,7 +744,7 @@ class _TabBarViewState extends State<TabBarView> {
if
(
integralScrollOffset
==
_pageController
.
page
)
{
_offsetBias
=
0.0
;
// The animation duration is short since the tab indicator and this
// page
able list
have already moved.
// page
view
have already moved.
_controller
.
animateTo
(
integralScrollOffset
.
floor
(),
duration:
const
Duration
(
milliseconds:
30
)
...
...
packages/flutter/lib/src/widgets/pageable_list.dart
deleted
100644 → 0
View file @
b4ec00c2
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'dart:async'
;
import
'package:flutter/rendering.dart'
show
RenderList
,
ViewportDimensions
;
import
'basic.dart'
;
import
'framework.dart'
;
import
'scroll_behavior.dart'
;
import
'scroll_configuration.dart'
;
import
'scrollable.dart'
;
import
'virtual_viewport.dart'
;
/// Controls how a pageable list should behave during a fling.
enum
PageableListFlingBehavior
{
/// A fling gesture can scroll the list by more than one page.
canFlingAcrossMultiplePages
,
/// A fling gesture can scroll the list by at most one page.
stopAtNextPage
}
/// A base class for widgets that display one page at a time.
///
/// [Pageable] widgets are similar to [Scrollable] except that they display a
/// single child at a time. When being scrolled, they can display adjacent
/// pages, but when the user stops scrolling, they settle their scroll offset to
/// a value that shows a single page.
///
/// [Pageable] uses different units for its scroll offset than [Scrollable]. One
/// unit of scroll offset corresponds to one child widget, which means a scroll
/// offset of 2.75 indicates that the viewport is three quarters of the way
/// between the child with index 2 and the child with index 3.
///
/// Widgets that subclass [Pageable] typically use state objects that subclass
/// [PageableState].
///
/// See also:
///
/// * [PageableList], which pages through an iterable list of children.
/// * [PageableLazyList], which pages through a lazily constructed list of
/// children.
abstract
class
Pageable
extends
Scrollable
{
/// Initializes fields for subclasses.
///
/// The [scrollDirection], [scrollAnchor], and [itemsSnapAlignment] arguments
/// must not be null.
Pageable
({
Key
key
,
double
initialScrollOffset
,
Axis
scrollDirection:
Axis
.
vertical
,
ViewportAnchor
scrollAnchor:
ViewportAnchor
.
start
,
ScrollListener
onScrollStart
,
ScrollListener
onScroll
,
ScrollListener
onScrollEnd
,
SnapOffsetCallback
snapOffsetCallback
,
this
.
itemsWrap
:
false
,
this
.
itemsSnapAlignment
:
PageableListFlingBehavior
.
stopAtNextPage
,
this
.
onPageChanged
,
this
.
duration
:
const
Duration
(
milliseconds:
200
),
this
.
curve
:
Curves
.
ease
})
:
super
(
key:
key
,
initialScrollOffset:
initialScrollOffset
,
scrollDirection:
scrollDirection
,
scrollAnchor:
scrollAnchor
,
onScrollStart:
onScrollStart
,
onScroll:
onScroll
,
onScrollEnd:
onScrollEnd
,
snapOffsetCallback:
snapOffsetCallback
)
{
assert
(
itemsSnapAlignment
!=
null
);
}
/// Whether the first item should be revealed after scrolling past the last item.
final
bool
itemsWrap
;
/// Controls whether a fling always reveals the adjacent item or whether flings can traverse many items.
final
PageableListFlingBehavior
itemsSnapAlignment
;
/// Called when the currently visible page changes.
final
ValueChanged
<
int
>
onPageChanged
;
/// The duration used when animating to a given page.
final
Duration
duration
;
/// The animation curve to use when animating to a given page.
final
Curve
curve
;
/// The number of items, one per page, to display.
int
get
itemCount
;
}
/// A widget that pages through an iterable list of children.
///
/// A [PageableList] displays a single child at a time. When being scrolled, it
/// can display adjacent pages, but when the user stops scrolling, it settles
/// its scroll offset to a value that shows a single page.
///
/// See also:
///
/// * [PageableLazyList], which pages through a lazily constructed list of
/// children.
class
PageableList
extends
Pageable
{
/// Creates a widget that pages through an iterable list of children.
///
/// The [scrollDirection], [scrollAnchor], and [itemsSnapAlignment] arguments
/// must not be null.
PageableList
({
Key
key
,
double
initialScrollOffset
,
Axis
scrollDirection:
Axis
.
vertical
,
ViewportAnchor
scrollAnchor:
ViewportAnchor
.
start
,
ScrollListener
onScrollStart
,
ScrollListener
onScroll
,
ScrollListener
onScrollEnd
,
SnapOffsetCallback
snapOffsetCallback
,
bool
itemsWrap:
false
,
PageableListFlingBehavior
itemsSnapAlignment:
PageableListFlingBehavior
.
stopAtNextPage
,
ValueChanged
<
int
>
onPageChanged
,
Duration
duration:
const
Duration
(
milliseconds:
200
),
Curve
curve:
Curves
.
ease
,
this
.
children
:
const
<
Widget
>[],
})
:
super
(
key:
key
,
initialScrollOffset:
initialScrollOffset
,
scrollDirection:
scrollDirection
,
scrollAnchor:
scrollAnchor
,
onScrollStart:
onScrollStart
,
onScroll:
onScroll
,
onScrollEnd:
onScrollEnd
,
snapOffsetCallback:
snapOffsetCallback
,
itemsWrap:
itemsWrap
,
itemsSnapAlignment:
itemsSnapAlignment
,
onPageChanged:
onPageChanged
,
duration:
duration
,
curve:
curve
);
/// The list of pages themselves.
final
Iterable
<
Widget
>
children
;
@override
int
get
itemCount
=>
children
?.
length
??
0
;
@override
PageableListState
<
PageableList
>
createState
()
=>
new
PageableListState
<
PageableList
>();
}
/// A widget that pages through a lazily constructed list of children.
///
/// A [PageableList] displays a single child at a time. When being scrolled, it
/// can display adjacent pages, but when the user stops scrolling, it settles
/// its scroll offset to a value that shows a single page.
///
/// See also:
///
/// * [PageableList], which pages through an iterable list of children.
class
PageableLazyList
extends
Pageable
{
/// Creates a widget that pages through a lazily constructed list of children.
///
/// The [scrollDirection], [scrollAnchor], and [itemsSnapAlignment] arguments
/// must not be null.
PageableLazyList
({
Key
key
,
double
initialScrollOffset
,
Axis
scrollDirection:
Axis
.
vertical
,
ViewportAnchor
scrollAnchor:
ViewportAnchor
.
start
,
ScrollListener
onScrollStart
,
ScrollListener
onScroll
,
ScrollListener
onScrollEnd
,
SnapOffsetCallback
snapOffsetCallback
,
PageableListFlingBehavior
itemsSnapAlignment:
PageableListFlingBehavior
.
stopAtNextPage
,
ValueChanged
<
int
>
onPageChanged
,
Duration
duration:
const
Duration
(
milliseconds:
200
),
Curve
curve:
Curves
.
ease
,
this
.
itemCount
:
0
,
this
.
itemBuilder
})
:
super
(
key:
key
,
initialScrollOffset:
initialScrollOffset
,
scrollDirection:
scrollDirection
,
scrollAnchor:
scrollAnchor
,
onScrollStart:
onScrollStart
,
onScroll:
onScroll
,
onScrollEnd:
onScrollEnd
,
snapOffsetCallback:
snapOffsetCallback
,
itemsWrap:
false
,
itemsSnapAlignment:
itemsSnapAlignment
,
onPageChanged:
onPageChanged
,
duration:
duration
,
curve:
curve
);
/// The total number of list items.
@override
final
int
itemCount
;
/// A function that returns the pages themselves.
final
ItemListBuilder
itemBuilder
;
@override
_PageableLazyListState
createState
()
=>
new
_PageableLazyListState
();
}
/// State for widgets that subclass [Pageable].
///
/// Specializes [ScrollableState] to support page-based scrolling.
///
/// Subclasses typically override [buildContent] to build viewports.
abstract
class
PageableState
<
T
extends
Pageable
>
extends
ScrollableState
<
T
>
{
int
get
_itemCount
=>
config
.
itemCount
;
int
_previousItemCount
;
/// Convert from the item based scroll units to logical pixels.
double
get
pixelsPerScrollUnit
{
final
RenderBox
box
=
context
.
findRenderObject
();
if
(
box
==
null
||
!
box
.
hasSize
)
return
0.0
;
switch
(
config
.
scrollDirection
)
{
case
Axis
.
horizontal
:
return
box
.
size
.
width
;
case
Axis
.
vertical
:
return
box
.
size
.
height
;
}
assert
(
config
.
scrollDirection
!=
null
);
return
null
;
}
@override
double
pixelOffsetToScrollOffset
(
double
pixelOffset
)
{
final
double
unit
=
pixelsPerScrollUnit
;
return
super
.
pixelOffsetToScrollOffset
(
unit
==
0.0
?
0.0
:
pixelOffset
/
unit
);
}
@override
double
scrollOffsetToPixelOffset
(
double
scrollOffset
)
{
return
super
.
scrollOffsetToPixelOffset
(
scrollOffset
*
pixelsPerScrollUnit
);
}
int
_scrollOffsetToPageIndex
(
double
scrollOffset
)
{
int
itemCount
=
_itemCount
;
if
(
itemCount
==
0
)
return
0
;
int
scrollIndex
=
scrollOffset
.
floor
();
switch
(
config
.
scrollAnchor
)
{
case
ViewportAnchor
.
start
:
return
scrollIndex
%
itemCount
;
case
ViewportAnchor
.
end
:
return
(
_itemCount
-
scrollIndex
-
1
)
%
itemCount
;
}
assert
(
config
.
scrollAnchor
!=
null
);
return
null
;
}
@override
void
didUpdateConfig
(
Pageable
oldConfig
)
{
super
.
didUpdateConfig
(
oldConfig
);
bool
scrollBehaviorUpdateNeeded
=
config
.
scrollDirection
!=
oldConfig
.
scrollDirection
;
if
(
config
.
itemsWrap
!=
oldConfig
.
itemsWrap
)
scrollBehaviorUpdateNeeded
=
true
;
if
(
_itemCount
!=
_previousItemCount
)
{
_previousItemCount
=
_itemCount
;
scrollBehaviorUpdateNeeded
=
true
;
}
if
(
scrollBehaviorUpdateNeeded
)
_updateScrollBehavior
();
}
void
_updateScrollBehavior
()
{
didUpdateScrollBehavior
(
scrollBehavior
.
updateExtents
(
contentExtent:
_itemCount
.
toDouble
(),
containerExtent:
1.0
,
scrollOffset:
scrollOffset
));
}
UnboundedBehavior
_unboundedBehavior
;
OverscrollBehavior
_overscrollBehavior
;
@override
ExtentScrollBehavior
get
scrollBehavior
{
if
(
config
.
itemsWrap
)
{
_unboundedBehavior
??=
new
UnboundedBehavior
(
platform:
platform
);
return
_unboundedBehavior
;
}
_overscrollBehavior
??=
new
OverscrollBehavior
(
platform:
platform
);
return
_overscrollBehavior
;
}
/// Returns the style of scrolling to use.
///
/// By default, defers to the nearest [ScrollConfiguration].
TargetPlatform
get
platform
=>
ScrollConfiguration
.
of
(
context
)?.
platform
;
@override
ExtentScrollBehavior
createScrollBehavior
()
=>
scrollBehavior
;
@override
bool
get
shouldSnapScrollOffset
=>
config
.
itemsSnapAlignment
==
PageableListFlingBehavior
.
canFlingAcrossMultiplePages
;
@override
double
snapScrollOffset
(
double
newScrollOffset
)
{
final
double
previousItemOffset
=
newScrollOffset
.
floorToDouble
();
final
double
nextItemOffset
=
newScrollOffset
.
ceilToDouble
();
return
(
newScrollOffset
-
previousItemOffset
<
0.5
?
previousItemOffset
:
nextItemOffset
)
.
clamp
(
scrollBehavior
.
minScrollOffset
,
scrollBehavior
.
maxScrollOffset
);
}
Future
<
Null
>
_flingToAdjacentItem
(
double
scrollVelocity
)
{
final
double
newScrollOffset
=
snapScrollOffset
(
scrollOffset
+
scrollVelocity
.
sign
)
.
clamp
(
snapScrollOffset
(
scrollOffset
-
0.50001
),
snapScrollOffset
(
scrollOffset
+
0.5
));
return
scrollTo
(
newScrollOffset
,
duration:
config
.
duration
,
curve:
config
.
curve
)
.
then
<
Null
>(
_notifyPageChanged
);
}
@override
Future
<
Null
>
fling
(
double
scrollVelocity
)
{
switch
(
config
.
itemsSnapAlignment
)
{
case
PageableListFlingBehavior
.
canFlingAcrossMultiplePages
:
return
(
super
.
fling
(
scrollVelocity
)).
then
<
Null
>(
_notifyPageChanged
);
case
PageableListFlingBehavior
.
stopAtNextPage
:
return
_flingToAdjacentItem
(
scrollVelocity
);
}
assert
(
config
.
itemsSnapAlignment
!=
null
);
return
null
;
}
@override
Future
<
Null
>
settleScrollOffset
()
{
return
scrollTo
(
snapScrollOffset
(
scrollOffset
),
duration:
config
.
duration
,
curve:
config
.
curve
)
.
then
<
Null
>(
_notifyPageChanged
);
}
void
_notifyPageChanged
(
Null
value
)
{
if
(
config
.
onPageChanged
!=
null
)
config
.
onPageChanged
(
_scrollOffsetToPageIndex
(
scrollOffset
));
}
}
/// State for a [PageableList] widget.
///
/// Widgets that subclass [PageableList] can subclass this class to have
/// sensible default behaviors for pageable lists.
class
PageableListState
<
T
extends
PageableList
>
extends
PageableState
<
T
>
{
@override
Widget
buildContent
(
BuildContext
context
)
{
return
new
PageViewport
(
itemsWrap:
config
.
itemsWrap
,
mainAxis:
config
.
scrollDirection
,
anchor:
config
.
scrollAnchor
,
startOffset:
scrollOffset
,
children:
config
.
children
);
}
}
class
_PageableLazyListState
extends
PageableState
<
PageableLazyList
>
{
@override
Widget
buildContent
(
BuildContext
context
)
{
return
new
LazyPageViewport
(
mainAxis:
config
.
scrollDirection
,
anchor:
config
.
scrollAnchor
,
startOffset:
scrollOffset
,
itemCount:
config
.
itemCount
,
itemBuilder:
config
.
itemBuilder
);
}
}
class
_VirtualPageViewport
extends
VirtualViewport
{
_VirtualPageViewport
(
this
.
startOffset
,
this
.
mainAxis
,
this
.
anchor
,
this
.
itemsWrap
)
{
assert
(
mainAxis
!=
null
);
assert
(
anchor
!=
null
);
}
@override
final
double
startOffset
;
/// The direction in which the children are permitted to be larger than the viewport.
///
/// The children are given layout constraints that are fully unconstrained
/// along the main axis (e.g., children can be as tall as they want if the
/// main axis is vertical).
final
Axis
mainAxis
;
/// Whether to place first child at the start of the container or the last
/// child at the end of the container, when the viewport has not been offset.
///
/// For example, if the [mainAxis] is [Axis.vertical] and
/// there are enough items to overflow the container, then
/// [ViewportAnchor.start] means that the top of the first item
/// should be aligned with the top of the viewport with the last
/// item below the bottom, and [ViewportAnchor.end] means the bottom
/// of the last item should be aligned with the bottom of the
/// viewport, with the first item above the top.
///
/// This also affects whether, when an item is added or removed, the
/// displacement will be towards the first item or the last item.
/// Continuing the earlier example, if a new item is inserted in the
/// middle of the list, in the [ViewportAnchor.start] case the items
/// after it (with greater indices, down to the item with the
/// highest index) will be pushed down, while in the
/// [ViewportAnchor.end] case the items before it (with lower
/// indices, up to the item with the index 0) will be pushed up.
final
ViewportAnchor
anchor
;
/// Whether the first item should be revealed after scrolling past the last item.
final
bool
itemsWrap
;
@override
RenderList
createRenderObject
(
BuildContext
context
)
=>
new
RenderList
();
@override
_VirtualPageViewportElement
createElement
()
=>
new
_VirtualPageViewportElement
(
this
);
}
class
_VirtualPageViewportElement
extends
VirtualViewportElement
{
_VirtualPageViewportElement
(
_VirtualPageViewport
widget
)
:
super
(
widget
);
@override
_VirtualPageViewport
get
widget
=>
super
.
widget
;
@override
RenderList
get
renderObject
=>
super
.
renderObject
;
@override
int
get
materializedChildBase
=>
_materializedChildBase
;
int
_materializedChildBase
;
@override
int
get
materializedChildCount
=>
_materializedChildCount
;
int
_materializedChildCount
;
@override
double
get
startOffsetBase
=>
_startOffsetBase
;
double
_startOffsetBase
;
@override
double
get
startOffsetLimit
=>
_startOffsetLimit
;
double
_startOffsetLimit
;
@override
double
scrollOffsetToPixelOffset
(
double
scrollOffset
)
{
if
(
_containerExtent
==
null
)
return
0.0
;
return
super
.
scrollOffsetToPixelOffset
(
scrollOffset
)
*
_containerExtent
;
}
@override
void
updateRenderObject
(
_VirtualPageViewport
oldWidget
)
{
renderObject
..
mainAxis
=
widget
.
mainAxis
;
super
.
updateRenderObject
(
oldWidget
);
}
double
_containerExtent
;
void
_updateViewportDimensions
()
{
final
Size
containerSize
=
renderObject
.
size
;
Size
materializedContentSize
;
switch
(
widget
.
mainAxis
)
{
case
Axis
.
vertical
:
materializedContentSize
=
new
Size
(
containerSize
.
width
,
_materializedChildCount
*
containerSize
.
height
);
break
;
case
Axis
.
horizontal
:
materializedContentSize
=
new
Size
(
_materializedChildCount
*
containerSize
.
width
,
containerSize
.
height
);
break
;
}
renderObject
.
dimensions
=
new
ViewportDimensions
(
containerSize:
containerSize
,
contentSize:
materializedContentSize
);
}
@override
void
layout
(
BoxConstraints
constraints
)
{
final
int
length
=
renderObject
.
virtualChildCount
;
switch
(
widget
.
mainAxis
)
{
case
Axis
.
vertical
:
_containerExtent
=
renderObject
.
size
.
height
;
break
;
case
Axis
.
horizontal
:
_containerExtent
=
renderObject
.
size
.
width
;
break
;
}
if
(
length
==
0
)
{
_materializedChildBase
=
0
;
_materializedChildCount
=
0
;
_startOffsetBase
=
0.0
;
_startOffsetLimit
=
double
.
INFINITY
;
}
else
{
int
startItem
=
widget
.
startOffset
.
floor
();
int
limitItem
=
(
widget
.
startOffset
+
1.0
).
ceil
();
if
(!
widget
.
itemsWrap
)
{
startItem
=
startItem
.
clamp
(
0
,
length
);
limitItem
=
limitItem
.
clamp
(
0
,
length
);
}
_materializedChildBase
=
startItem
;
_materializedChildCount
=
limitItem
-
startItem
;
_startOffsetBase
=
startItem
.
toDouble
();
_startOffsetLimit
=
(
limitItem
-
1
).
toDouble
();
if
(
widget
.
anchor
==
ViewportAnchor
.
end
)
_materializedChildBase
=
(
length
-
_materializedChildBase
-
_materializedChildCount
)
%
length
;
}
_updateViewportDimensions
();
super
.
layout
(
constraints
);
}
}
/// A virtual viewport that displays a single child at a time.
///
/// Useful for [Pageable] widgets.
///
/// One unit of start offset corresponds to one child widget, which means a
/// start offset of 2.75 indicates that the viewport is three quarters of the
/// way between the child with index 2 and the child with index 3.
///
/// [PageViewport] differs from [LazyPageViewport] in that [PageViewport] uses
/// an [Iterable] list of children. That makes [PageViewport] suitable for a
/// large (but not extremely large or infinite) list of children.
class
PageViewport
extends
_VirtualPageViewport
with
VirtualViewportFromIterable
{
/// Creates a virtual viewport that displays a single child at a time.
///
/// The [mainAxis] and [anchor] arguments must not be null.
PageViewport
({
double
startOffset:
0.0
,
Axis
mainAxis:
Axis
.
vertical
,
ViewportAnchor
anchor:
ViewportAnchor
.
start
,
bool
itemsWrap:
false
,
this
.
children
:
const
<
Widget
>[],
})
:
super
(
startOffset
,
mainAxis
,
anchor
,
itemsWrap
);
@override
final
Iterable
<
Widget
>
children
;
}
/// A virtual viewport that displays a single child at a time.
///
/// Useful for [Pageable] widgets.
///
/// One unit of start offset corresponds to one child widget, which means a
/// start offset of 2.75 indicates that the viewport is three quarters of the
/// way between the child with index 2 and the child with index 3.
///
/// [LazyPageViewport] differs from [PageViewport] in that [LazyPageViewport]
/// uses an [ItemListBuilder] to lazily create children. That makes
/// [LazyPageViewport] suitable for an extremely large or infinite list of
/// children but also makes it more verbose than [PageViewport].
class
LazyPageViewport
extends
_VirtualPageViewport
with
VirtualViewportFromBuilder
{
/// Creates a virtual viewport that displays a single child at a time.
///
/// The [mainAxis] and [anchor] arguments must not be null.
LazyPageViewport
({
double
startOffset:
0.0
,
Axis
mainAxis:
Axis
.
vertical
,
ViewportAnchor
anchor:
ViewportAnchor
.
start
,
this
.
itemCount
,
this
.
itemBuilder
})
:
super
(
startOffset
,
mainAxis
,
anchor
,
false
// Don't support wrapping yet.
);
@override
final
int
itemCount
;
@override
final
ItemListBuilder
itemBuilder
;
}
packages/flutter/lib/src/widgets/scrollable.dart
View file @
1ec625ff
...
...
@@ -1239,7 +1239,6 @@ class ScrollNotification extends Notification {
///
/// * [Block], if your single child is a [Column].
/// * [ScrollableList], if you have many identically-sized children.
/// * [PageableList], if you have children that each take the entire screen.
/// * [ScrollableGrid], if your children are in a grid pattern.
/// * [LazyBlock], if you have many children of varying sizes.
class
ScrollableViewport
extends
StatelessWidget
{
...
...
packages/flutter/lib/src/widgets/virtual_viewport.dart
View file @
1ec625ff
...
...
@@ -287,7 +287,7 @@ class _IterableWidgetProvider extends _WidgetProvider {
/// Signature of a callback that returns the sublist of widgets in the given range.
///
/// Used by [
PageableList.itemBuilder], [
ScrollableLazyList.itemBuilder], etc.
/// Used by [ScrollableLazyList.itemBuilder], etc.
typedef
List
<
Widget
>
ItemListBuilder
(
BuildContext
context
,
int
start
,
int
count
);
/// A VirtualViewport that represents its children using [ItemListBuilder].
...
...
packages/flutter/lib/widgets.dart
View file @
1ec625ff
...
...
@@ -40,7 +40,6 @@ export 'src/widgets/overlay.dart';
export
'src/widgets/overscroll_indicator.dart'
;
export
'src/widgets/page_storage.dart'
;
export
'src/widgets/page_view.dart'
;
export
'src/widgets/pageable_list.dart'
;
export
'src/widgets/pages.dart'
;
export
'src/widgets/performance_overlay.dart'
;
export
'src/widgets/placeholder.dart'
;
...
...
packages/flutter/test/widgets/pageable_list_test.dart
View file @
1ec625ff
...
...
@@ -21,23 +21,22 @@ Widget buildPage(int page) {
}
Widget
buildFrame
(
{
bool
itemsWrap:
false
,
ViewportAnchor
scrollAnchor:
ViewportAnchor
.
start
,
bool
reverse:
false
,
List
<
int
>
pages:
defaultPages
})
{
final
PageableList
list
=
new
PageableList
(
children:
pages
.
map
(
buildPage
),
itemsWrap:
itemsWrap
,
final
PageView
child
=
new
PageView
(
scrollDirection:
Axis
.
horizontal
,
scrollAnchor:
scrollAnchor
,
onPageChanged:
(
int
page
)
{
currentPage
=
page
;
}
reverse:
reverse
,
onPageChanged:
(
int
page
)
{
currentPage
=
page
;
},
children:
pages
.
map
(
buildPage
).
toList
(),
);
// The test framework forces the frame to be 800x600, so we need to create
// an outer container where we can change the size.
return
new
Center
(
child:
new
Container
(
width:
pageSize
.
width
,
height:
pageSize
.
height
,
child:
list
)
width:
pageSize
.
width
,
height:
pageSize
.
height
,
child:
child
,
),
);
}
...
...
@@ -45,9 +44,8 @@ Future<Null> page(WidgetTester tester, Offset offset) {
return
TestAsyncUtils
.
guard
(()
async
{
String
itemText
=
currentPage
!=
null
?
currentPage
.
toString
()
:
'0'
;
await
tester
.
scroll
(
find
.
text
(
itemText
),
offset
);
// One frame to start the animation, a second to complete it.
await
tester
.
pump
();
await
tester
.
pump
(
const
Duration
(
seconds:
1
)
);
await
tester
.
pump
UntilNoTransientCallbacks
(
);
});
}
...
...
@@ -60,11 +58,11 @@ Future<Null> pageRight(WidgetTester tester) {
}
void
main
(
)
{
testWidgets
(
'Page
ableList
default control'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
new
Center
(
child:
new
Page
ableList
()));
testWidgets
(
'Page
View
default control'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
new
Center
(
child:
new
Page
View
()));
});
testWidgets
(
'Page
ableList with itemsWrap: false
'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'Page
View control test
'
,
(
WidgetTester
tester
)
async
{
currentPage
=
null
;
await
tester
.
pumpWidget
(
buildFrame
());
expect
(
currentPage
,
isNull
);
...
...
@@ -92,74 +90,18 @@ void main() {
expect
(
currentPage
,
equals
(
0
));
});
testWidgets
(
'PageableList with end scroll anchor'
,
(
WidgetTester
tester
)
async
{
currentPage
=
5
;
await
tester
.
pumpWidget
(
buildFrame
(
scrollAnchor:
ViewportAnchor
.
end
));
await
pageRight
(
tester
);
expect
(
currentPage
,
equals
(
4
));
expect
(
find
.
text
(
'0'
),
findsNothing
);
expect
(
find
.
text
(
'1'
),
findsNothing
);
expect
(
find
.
text
(
'2'
),
findsNothing
);
expect
(
find
.
text
(
'3'
),
findsNothing
);
expect
(
find
.
text
(
'4'
),
findsOneWidget
);
expect
(
find
.
text
(
'5'
),
findsNothing
);
await
pageLeft
(
tester
);
expect
(
currentPage
,
equals
(
5
));
expect
(
find
.
text
(
'0'
),
findsNothing
);
expect
(
find
.
text
(
'1'
),
findsNothing
);
expect
(
find
.
text
(
'2'
),
findsNothing
);
expect
(
find
.
text
(
'3'
),
findsNothing
);
expect
(
find
.
text
(
'4'
),
findsNothing
);
expect
(
find
.
text
(
'5'
),
findsOneWidget
);
await
pageLeft
(
tester
);
expect
(
currentPage
,
equals
(
5
));
expect
(
find
.
text
(
'0'
),
findsNothing
);
expect
(
find
.
text
(
'1'
),
findsNothing
);
expect
(
find
.
text
(
'2'
),
findsNothing
);
expect
(
find
.
text
(
'3'
),
findsNothing
);
expect
(
find
.
text
(
'4'
),
findsNothing
);
expect
(
find
.
text
(
'5'
),
findsOneWidget
);
});
testWidgets
(
'PageableList with itemsWrap: true'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'PageView with reverse'
,
(
WidgetTester
tester
)
async
{
currentPage
=
null
;
await
tester
.
pumpWidget
(
buildFrame
(
itemsWrap:
true
));
expect
(
currentPage
,
isNull
);
await
pageLeft
(
tester
);
expect
(
currentPage
,
equals
(
1
));
await
pageRight
(
tester
);
expect
(
currentPage
,
equals
(
0
));
await
pageRight
(
tester
);
expect
(
currentPage
,
equals
(
5
));
});
testWidgets
(
'PageableList with end and itemsWrap: true'
,
(
WidgetTester
tester
)
async
{
currentPage
=
5
;
await
tester
.
pumpWidget
(
buildFrame
(
itemsWrap:
true
,
scrollAnchor:
ViewportAnchor
.
end
));
await
tester
.
pumpWidget
(
buildFrame
(
reverse:
true
));
await
pageRight
(
tester
);
expect
(
currentPage
,
equals
(
4
));
expect
(
find
.
text
(
'0'
),
findsNothing
);
expect
(
find
.
text
(
'1'
),
findsNothing
);
expect
(
find
.
text
(
'2'
),
findsNothing
);
expect
(
find
.
text
(
'3'
),
findsNothing
);
expect
(
find
.
text
(
'4'
),
findsOneWidget
);
expect
(
find
.
text
(
'5'
),
findsNothing
);
await
pageLeft
(
tester
);
expect
(
currentPage
,
equals
(
5
));
expect
(
currentPage
,
equals
(
1
));
expect
(
find
.
text
(
'0'
),
findsNothing
);
expect
(
find
.
text
(
'1'
),
finds
Nothing
);
expect
(
find
.
text
(
'1'
),
finds
OneWidget
);
expect
(
find
.
text
(
'2'
),
findsNothing
);
expect
(
find
.
text
(
'3'
),
findsNothing
);
expect
(
find
.
text
(
'4'
),
findsNothing
);
expect
(
find
.
text
(
'5'
),
finds
OneWidget
);
expect
(
find
.
text
(
'5'
),
finds
Nothing
);
await
pageLeft
(
tester
);
expect
(
currentPage
,
equals
(
0
));
...
...
@@ -172,71 +114,13 @@ void main() {
expect
(
find
.
text
(
'5'
),
findsNothing
);
await
pageLeft
(
tester
);
expect
(
currentPage
,
equals
(
1
));
expect
(
find
.
text
(
'0'
),
findsNothing
);
expect
(
find
.
text
(
'1'
),
findsOneWidget
);
expect
(
find
.
text
(
'2'
),
findsNothing
);
expect
(
find
.
text
(
'3'
),
findsNothing
);
expect
(
find
.
text
(
'4'
),
findsNothing
);
expect
(
find
.
text
(
'5'
),
findsNothing
);
});
testWidgets
(
'PageableList with two items'
,
(
WidgetTester
tester
)
async
{
currentPage
=
null
;
await
tester
.
pumpWidget
(
buildFrame
(
itemsWrap:
true
,
pages:
<
int
>[
0
,
1
]));
expect
(
currentPage
,
isNull
);
await
pageLeft
(
tester
);
expect
(
currentPage
,
equals
(
1
));
await
pageRight
(
tester
);
expect
(
currentPage
,
equals
(
0
));
await
pageRight
(
tester
);
expect
(
currentPage
,
equals
(
1
));
});
testWidgets
(
'PageableList with one item'
,
(
WidgetTester
tester
)
async
{
currentPage
=
null
;
await
tester
.
pumpWidget
(
buildFrame
(
itemsWrap:
true
,
pages:
<
int
>[
0
]));
expect
(
currentPage
,
isNull
);
await
pageLeft
(
tester
);
expect
(
currentPage
,
equals
(
0
));
await
pageRight
(
tester
);
expect
(
currentPage
,
equals
(
0
));
await
pageRight
(
tester
);
expect
(
currentPage
,
equals
(
0
));
});
testWidgets
(
'PageableList with no items'
,
(
WidgetTester
tester
)
async
{
currentPage
=
null
;
await
tester
.
pumpWidget
(
buildFrame
(
itemsWrap:
true
,
pages:
<
int
>[]));
expect
(
currentPage
,
isNull
);
});
testWidgets
(
'PageableList resize parent'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
new
Container
());
currentPage
=
null
;
await
tester
.
pumpWidget
(
buildFrame
(
itemsWrap:
true
));
expect
(
currentPage
,
isNull
);
await
pageRight
(
tester
);
expect
(
currentPage
,
equals
(
5
));
Size
boxSize
=
globalKeys
[
5
].
currentContext
.
size
;
expect
(
boxSize
.
width
,
equals
(
pageSize
.
width
));
expect
(
boxSize
.
height
,
equals
(
pageSize
.
height
));
pageSize
=
new
Size
(
pageSize
.
height
,
pageSize
.
width
);
await
tester
.
pumpWidget
(
buildFrame
(
itemsWrap:
true
));
expect
(
find
.
text
(
'0'
),
findsNothing
);
expect
(
find
.
text
(
'0'
),
findsOneWidget
);
expect
(
find
.
text
(
'1'
),
findsNothing
);
expect
(
find
.
text
(
'2'
),
findsNothing
);
expect
(
find
.
text
(
'3'
),
findsNothing
);
expect
(
find
.
text
(
'4'
),
findsNothing
);
expect
(
find
.
text
(
'5'
),
findsOneWidget
);
boxSize
=
globalKeys
[
5
].
currentContext
.
size
;
expect
(
boxSize
.
width
,
equals
(
pageSize
.
width
));
expect
(
boxSize
.
height
,
equals
(
pageSize
.
height
));
expect
(
find
.
text
(
'5'
),
findsNothing
);
});
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment