|
|
|
|
|
|
|
|
|
|
float _viewportFraction; |
|
|
|
|
|
|
|
float _initialPageOffset { |
|
|
|
get { |
|
|
|
return Mathf.Max(0, viewportDimension * (viewportFraction - 1) / 2); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return page * viewportDimension * viewportFraction; |
|
|
|
return page * viewportDimension * viewportFraction + _initialPageOffset; |
|
|
|
D.assert( |
|
|
|
pixels == null || (minScrollExtent != null && maxScrollExtent != null), |
|
|
|
() => "Page value is only available after content dimensions are established." |
|
|
|
); |
|
|
|
return getPageFromPixels(pixels.clamp(minScrollExtent, maxScrollExtent), |
|
|
|
viewportDimension); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
return result; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public override bool applyContentDimensions(float minScrollExtent, float maxScrollExtent) { |
|
|
|
float newMinScrollExtent = minScrollExtent + _initialPageOffset; |
|
|
|
return base.applyContentDimensions( |
|
|
|
newMinScrollExtent, |
|
|
|
Mathf.Max(newMinScrollExtent, maxScrollExtent - _initialPageOffset) |
|
|
|
); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public class _ForceImplicitScrollPhysics : ScrollPhysics { |
|
|
|
public _ForceImplicitScrollPhysics( |
|
|
|
bool allowImplicitScrolling = false, |
|
|
|
ScrollPhysics parent = null |
|
|
|
) : base(parent: parent) { |
|
|
|
D.assert(allowImplicitScrolling != null); |
|
|
|
} |
|
|
|
|
|
|
|
public override ScrollPhysics applyTo(ScrollPhysics ancestor) { |
|
|
|
return new _ForceImplicitScrollPhysics( |
|
|
|
allowImplicitScrolling: allowImplicitScrolling, |
|
|
|
parent: buildParent(ancestor) |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
public readonly bool allowImplicitScrolling; |
|
|
|
} |
|
|
|
|
|
|
|
public class PageScrollPhysics : ScrollPhysics { |
|
|
|
|
|
|
return new PageScrollPhysics(parent: buildParent(ancestor)); |
|
|
|
} |
|
|
|
|
|
|
|
float _getPage(ScrollPosition position) { |
|
|
|
float _getPage(ScrollMetrics position) { |
|
|
|
if (position is _PagePosition) { |
|
|
|
return ((_PagePosition) position).page; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
float _getPixels(ScrollPosition position, float page) { |
|
|
|
float _getPixels(ScrollMetrics position, float page) { |
|
|
|
if (position is _PagePosition) { |
|
|
|
return ((_PagePosition) position).getPixelsFromPage(page); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
float _getTargetPixels(ScrollPosition position, Tolerance tolerance, float velocity) { |
|
|
|
float _getTargetPixels(ScrollMetrics position, Tolerance tolerance, float velocity) { |
|
|
|
float page = _getPage(position); |
|
|
|
if (velocity < -tolerance.velocity) { |
|
|
|
page -= 0.5f; |
|
|
|
|
|
|
DragStartBehavior dragStartBehavior = DragStartBehavior.start, |
|
|
|
IndexedWidgetBuilder itemBuilder = null, |
|
|
|
SliverChildDelegate childDelegate = null, |
|
|
|
int itemCount = 0 |
|
|
|
int itemCount = 0, |
|
|
|
bool allowImplicitScrolling = false |
|
|
|
) : base(key: key) { |
|
|
|
this.scrollDirection = scrollDirection; |
|
|
|
this.reverse = reverse; |
|
|
|
|
|
|
this.dragStartBehavior = dragStartBehavior; |
|
|
|
this.controller = controller ?? PageViewUtils._defaultPageController; |
|
|
|
this.allowImplicitScrolling = allowImplicitScrolling; |
|
|
|
if (itemBuilder != null) { |
|
|
|
childrenDelegate = new SliverChildBuilderDelegate(itemBuilder, childCount: itemCount); |
|
|
|
} |
|
|
|
|
|
|
bool pageSnapping = true, |
|
|
|
ValueChanged<int> onPageChanged = null, |
|
|
|
int itemCount = 0, |
|
|
|
bool allowImplicitScrolling = false, |
|
|
|
DragStartBehavior dragStartBehavior = DragStartBehavior.start |
|
|
|
) { |
|
|
|
return new PageView( |
|
|
|
|
|
|
pageSnapping: pageSnapping, |
|
|
|
onPageChanged: onPageChanged, |
|
|
|
itemCount: itemCount, |
|
|
|
allowImplicitScrolling: allowImplicitScrolling, |
|
|
|
dragStartBehavior: dragStartBehavior |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
public readonly SliverChildDelegate childrenDelegate; |
|
|
|
|
|
|
|
public readonly DragStartBehavior dragStartBehavior; |
|
|
|
|
|
|
|
public readonly bool allowImplicitScrolling; |
|
|
|
|
|
|
|
public override State createState() { |
|
|
|
return new _PageViewState(); |
|
|
|
|
|
|
|
|
|
|
public override Widget build(BuildContext context) { |
|
|
|
AxisDirection axisDirection = _getDirection(context); |
|
|
|
ScrollPhysics physics = widget.pageSnapping |
|
|
|
ScrollPhysics physics = new _ForceImplicitScrollPhysics( |
|
|
|
allowImplicitScrolling: widget.allowImplicitScrolling |
|
|
|
).applyTo(widget.pageSnapping |
|
|
|
: widget.physics; |
|
|
|
: widget.physics); |
|
|
|
|
|
|
|
return new NotificationListener<ScrollNotification>( |
|
|
|
onNotification: (ScrollNotification notification) => { |
|
|
|
|
|
|
physics: physics, |
|
|
|
viewportBuilder: (BuildContext _context, ViewportOffset position) => { |
|
|
|
return new Viewport( |
|
|
|
cacheExtent: 0.0f, |
|
|
|
cacheExtent: widget.allowImplicitScrolling ? 1.0f : 0.0f, |
|
|
|
cacheExtentStyle: CacheExtentStyle.viewport, |
|
|
|
axisDirection: axisDirection, |
|
|
|
offset: position, |
|
|
|
slivers: new List<Widget> { |
|
|
|
|
|
|
description.add(new DiagnosticsProperty<ScrollPhysics>("physics", widget.physics, showName: false)); |
|
|
|
description.add(new FlagProperty("pageSnapping", value: widget.pageSnapping, |
|
|
|
ifFalse: "snapping disabled")); |
|
|
|
description.add(new FlagProperty("allowImplicitScrolling", value: widget.allowImplicitScrolling, ifTrue: "allow implicit scrolling")); |
|
|
|
} |
|
|
|
} |
|
|
|
} |