Document more scrolling classes (#9684)
This commit is contained in:
parent
a4ba761bea
commit
c6b0f833af
@ -1261,6 +1261,10 @@ abstract class RenderSliverSingleBoxAdapter extends RenderSliver with RenderObje
|
||||
child.parentData = new SliverPhysicalParentData();
|
||||
}
|
||||
|
||||
/// Sets the [SliverPhysicalParentData.paintOffset] for the given child
|
||||
/// according to the [SliverConstraints.axisDirection] and
|
||||
/// [SliverConstraints.growthDirection] and the given geometry.
|
||||
@protected
|
||||
void setChildParentData(RenderObject child, SliverConstraints constraints, SliverGeometry geometry) {
|
||||
final SliverPhysicalParentData childParentData = child.parentData;
|
||||
assert(constraints.axisDirection != null);
|
||||
|
@ -24,7 +24,8 @@ import 'scroll_view.dart';
|
||||
import 'sliver.dart';
|
||||
import 'ticker_provider.dart';
|
||||
|
||||
typedef List<Widget> NestedScrollViewOuterSliversBuilder(BuildContext context, bool innerBoxIsScrolled);
|
||||
/// Signature used by [NestedScrollView] for building its header.
|
||||
typedef List<Widget> NestedScrollViewHeaderSliversBuilder(BuildContext context, bool innerBoxIsScrolled);
|
||||
|
||||
class NestedScrollView extends StatefulWidget {
|
||||
NestedScrollView({
|
||||
@ -49,7 +50,7 @@ class NestedScrollView extends StatefulWidget {
|
||||
|
||||
final ScrollPhysics physics;
|
||||
|
||||
final NestedScrollViewOuterSliversBuilder headerSliverBuilder;
|
||||
final NestedScrollViewHeaderSliversBuilder headerSliverBuilder;
|
||||
|
||||
final Widget body;
|
||||
|
||||
@ -415,9 +416,9 @@ class _NestedScrollCoorindator implements ScrollActivityDelegate {
|
||||
|
||||
Drag drag(DragStartDetails details, VoidCallback dragCancelCallback) {
|
||||
final ScrollDragController drag = new ScrollDragController(
|
||||
this,
|
||||
details,
|
||||
dragCancelCallback,
|
||||
delegate: this,
|
||||
details: details,
|
||||
onDragCanceled: dragCancelCallback,
|
||||
);
|
||||
beginActivity(
|
||||
new DragScrollActivity(_outerPosition, drag),
|
||||
|
@ -7,7 +7,17 @@ import 'package:flutter/foundation.dart';
|
||||
import 'framework.dart';
|
||||
import 'scroll_controller.dart';
|
||||
|
||||
/// Associates a [ScrollController] with a subtree.
|
||||
///
|
||||
/// When a [ScrollView] has [ScrollView.primary] set to true and is not given
|
||||
/// an explicit [ScrollController], the [ScrollView] uses [of] to find the
|
||||
/// [ScrollController] associated with its subtree.
|
||||
///
|
||||
/// This mechanism can be used to provide default behavior for scroll views in a
|
||||
/// subtree. For example, the [Scaffold] uses this mechanism to implement the
|
||||
/// scroll-to-top gesture on iOS.
|
||||
class PrimaryScrollController extends InheritedWidget {
|
||||
/// Creates a widget that associates a [ScrollController] with a subtree.
|
||||
const PrimaryScrollController({
|
||||
Key key,
|
||||
@required this.controller,
|
||||
@ -15,14 +25,21 @@ class PrimaryScrollController extends InheritedWidget {
|
||||
}) : assert(controller != null),
|
||||
super(key: key, child: child);
|
||||
|
||||
/// Creates a subtree without an associated [ScrollController].
|
||||
const PrimaryScrollController.none({
|
||||
Key key,
|
||||
@required Widget child
|
||||
}) : controller = null,
|
||||
super(key: key, child: child);
|
||||
|
||||
/// The [ScrollController] associated with the subtree.
|
||||
final ScrollController controller;
|
||||
|
||||
/// Returns the [ScrollController] most closely associated with the given
|
||||
/// context.
|
||||
///
|
||||
/// Returns null if there is no [ScrollController] associated with the given
|
||||
/// context.
|
||||
static ScrollController of(BuildContext context) {
|
||||
final PrimaryScrollController result = context.inheritFromWidgetOfExactType(PrimaryScrollController);
|
||||
return result?.controller;
|
||||
|
@ -17,13 +17,37 @@ import 'scroll_metrics.dart';
|
||||
import 'scroll_notification.dart';
|
||||
import 'ticker_provider.dart';
|
||||
|
||||
/// A backend for a [ScrollActivity].
|
||||
///
|
||||
/// Used by subclases of [ScrollActivity] to manipulate the scroll view that
|
||||
/// they are acting upon.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [ScrollActivity], which uses this class as its delegate.
|
||||
abstract class ScrollActivityDelegate {
|
||||
/// The direction in which the scroll view scrolls.
|
||||
AxisDirection get axisDirection;
|
||||
|
||||
/// Update the scroll position to the given pixel value.
|
||||
///
|
||||
/// Returns the overscroll, if any. See [ScrollPosition.setPixels] for more
|
||||
/// information.
|
||||
double setPixels(double pixels);
|
||||
|
||||
/// Updates the scroll position by the given amount.
|
||||
///
|
||||
/// Appropriate for when the user is directly manipulating the scroll
|
||||
/// position, for example by dragging the scroll view. Typically applies
|
||||
/// [ScrollPhysics.applyPhysicsToUserOffset] and other transformations that
|
||||
/// are appropriate for user-driving scrolling.
|
||||
void applyUserOffset(double delta);
|
||||
|
||||
/// Terminate the current activity and start an idle activity.
|
||||
void goIdle();
|
||||
|
||||
/// Terminate the current activity and start a ballistic activity with the
|
||||
/// given velocity.
|
||||
void goBallistic(double velocity);
|
||||
}
|
||||
|
||||
@ -31,11 +55,13 @@ abstract class ScrollActivityDelegate {
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [ScrollPositionWithSingleContext], which uses [ScrollActivity] objects to
|
||||
/// manage the [ScrollPosition] of a [Scrollable].
|
||||
/// * [ScrollPosition], which uses [ScrollActivity] objects to manage the
|
||||
/// [ScrollPosition] of a [Scrollable].
|
||||
abstract class ScrollActivity {
|
||||
/// Initializes [delegate] for subclasses.
|
||||
ScrollActivity(this._delegate);
|
||||
|
||||
/// The delegate that this activity will use to actuate the scroll view.
|
||||
ScrollActivityDelegate get delegate => _delegate;
|
||||
ScrollActivityDelegate _delegate;
|
||||
|
||||
@ -58,30 +84,43 @@ abstract class ScrollActivity {
|
||||
/// [ScrollActivityDelegate.goBallistic].
|
||||
void resetActivity() { }
|
||||
|
||||
/// Dispatch a [ScrollStartNotification] with the given metrics.
|
||||
void dispatchScrollStartNotification(ScrollMetrics metrics, BuildContext context) {
|
||||
new ScrollStartNotification(metrics: metrics, context: context).dispatch(context);
|
||||
}
|
||||
|
||||
/// Dispatch a [ScrollUpdateNotification] with the given metrics and scroll delta.
|
||||
void dispatchScrollUpdateNotification(ScrollMetrics metrics, BuildContext context, double scrollDelta) {
|
||||
new ScrollUpdateNotification(metrics: metrics, context: context, scrollDelta: scrollDelta).dispatch(context);
|
||||
}
|
||||
|
||||
/// Dispatch an [OverscrollNotification] with the given metrics and overscroll.
|
||||
void dispatchOverscrollNotification(ScrollMetrics metrics, BuildContext context, double overscroll) {
|
||||
new OverscrollNotification(metrics: metrics, context: context, overscroll: overscroll).dispatch(context);
|
||||
}
|
||||
|
||||
/// Dispatch a [ScrollEndNotification] with the given metrics and overscroll.
|
||||
void dispatchScrollEndNotification(ScrollMetrics metrics, BuildContext context) {
|
||||
new ScrollEndNotification(metrics: metrics, context: context).dispatch(context);
|
||||
}
|
||||
|
||||
/// Called when the user touches the scroll view that is performing this activity.
|
||||
void didTouch() { }
|
||||
|
||||
/// Called when the scroll view that is performing this activity changes its metrics.
|
||||
void applyNewDimensions() { }
|
||||
|
||||
/// Whether the scroll view should ignore pointer events while performing this
|
||||
/// activity.
|
||||
bool get shouldIgnorePointer;
|
||||
|
||||
/// Whether performing this activity constitutes scrolling.
|
||||
///
|
||||
/// Used, for example, to determine whether the user scroll direction is
|
||||
/// [ScrollDirection.idle].
|
||||
bool get isScrolling;
|
||||
|
||||
/// Called when the scroll view stops performing this activity.
|
||||
@mustCallSuper
|
||||
void dispose() {
|
||||
_delegate = null;
|
||||
@ -91,7 +130,11 @@ abstract class ScrollActivity {
|
||||
String toString() => '$runtimeType';
|
||||
}
|
||||
|
||||
/// A scroll activity that does nothing.
|
||||
///
|
||||
/// When a scroll view is not scrolling, it is performing the idle activity.
|
||||
class IdleScrollActivity extends ScrollActivity {
|
||||
/// Creates a scroll activity that does nothing.
|
||||
IdleScrollActivity(ScrollActivityDelegate delegate) : super(delegate);
|
||||
|
||||
@override
|
||||
@ -106,16 +149,31 @@ class IdleScrollActivity extends ScrollActivity {
|
||||
bool get isScrolling => false;
|
||||
}
|
||||
|
||||
/// Scrolls a scroll view as the user drags their finger across the screen.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [DragScrollActivity], which is the activity the scroll view performs
|
||||
/// while a drag is underway.
|
||||
class ScrollDragController implements Drag {
|
||||
ScrollDragController(
|
||||
ScrollActivityDelegate delegate,
|
||||
DragStartDetails details,
|
||||
/// Creates an object that scrolls a scroll view as the user drags their
|
||||
/// finger across the screen.
|
||||
///
|
||||
/// The [delegate] and `details` arguments must not be null.
|
||||
ScrollDragController({
|
||||
@required ScrollActivityDelegate delegate,
|
||||
@required DragStartDetails details,
|
||||
this.onDragCanceled,
|
||||
) : _delegate = delegate, _lastDetails = details;
|
||||
}) : _delegate = delegate, _lastDetails = details {
|
||||
assert(delegate != null);
|
||||
assert(details != null);
|
||||
}
|
||||
|
||||
/// The object that will actuate the scroll view as the user drags.
|
||||
ScrollActivityDelegate get delegate => _delegate;
|
||||
ScrollActivityDelegate _delegate;
|
||||
|
||||
/// Called when [dispose] is called.
|
||||
final VoidCallback onDragCanceled;
|
||||
|
||||
bool get _reversed => axisDirectionIsReversed(delegate.axisDirection);
|
||||
@ -159,6 +217,7 @@ class ScrollDragController implements Drag {
|
||||
delegate.goBallistic(0.0);
|
||||
}
|
||||
|
||||
/// Called when the delegate is no longer sending events to this object.
|
||||
@mustCallSuper
|
||||
void dispose() {
|
||||
_lastDetails = null;
|
||||
@ -166,11 +225,22 @@ class ScrollDragController implements Drag {
|
||||
onDragCanceled();
|
||||
}
|
||||
|
||||
/// The most recently observed [DragStartDetails], [DragUpdateDetails], or
|
||||
/// [DragEndDetails] object.
|
||||
dynamic get lastDetails => _lastDetails;
|
||||
dynamic _lastDetails;
|
||||
}
|
||||
|
||||
/// The activity a scroll view performs when a the user drags their finger
|
||||
/// across the screen.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [ScrollDragController], which listens to the [Drag] and actually scrolls
|
||||
/// the scroll view.
|
||||
class DragScrollActivity extends ScrollActivity {
|
||||
/// Creates an activity for when the user drags their finger across the
|
||||
/// screen.
|
||||
DragScrollActivity(
|
||||
ScrollActivityDelegate delegate,
|
||||
ScrollDragController controller,
|
||||
@ -228,9 +298,23 @@ class DragScrollActivity extends ScrollActivity {
|
||||
}
|
||||
}
|
||||
|
||||
/// An activity that animates a scroll view based on a physics [simulation].
|
||||
///
|
||||
/// A [BallisticScrollActivity] is typically used when the user lifts their
|
||||
/// finger off the screen to continue the scrolling gesture with the current velocity.
|
||||
///
|
||||
/// [BallisticScrollActivity] is also used to restore a scroll view to a valid
|
||||
/// scroll offset when the geometry of the scroll view changes. In these
|
||||
/// situations, the [simulation] typically starts with a zero velocity.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [DrivenScrollActivity], which animates a scroll view based on a set of
|
||||
/// animation parameters.
|
||||
class BallisticScrollActivity extends ScrollActivity {
|
||||
// ///
|
||||
// /// The velocity should be in logical pixels per second.
|
||||
/// Creates an activity that animates a scroll view based on a [simulation].
|
||||
///
|
||||
/// The [delegate], [simulation], and [vsync] arguments must not be null.
|
||||
BallisticScrollActivity(
|
||||
ScrollActivityDelegate delegate,
|
||||
Simulation simulation,
|
||||
@ -245,6 +329,8 @@ class BallisticScrollActivity extends ScrollActivity {
|
||||
.whenComplete(_end); // won't trigger if we dispose _controller first
|
||||
}
|
||||
|
||||
/// The velocity at which the scroll offset is currently changing (in logical
|
||||
/// pixels per second).
|
||||
double get velocity => _controller.velocity;
|
||||
|
||||
AnimationController _controller;
|
||||
@ -271,8 +357,8 @@ class BallisticScrollActivity extends ScrollActivity {
|
||||
|
||||
/// Move the position to the given location.
|
||||
///
|
||||
/// If the new position was fully applied, return true.
|
||||
/// If there was any overflow, return false.
|
||||
/// If the new position was fully applied, returns true. If there was any
|
||||
/// overflow, returns false.
|
||||
///
|
||||
/// The default implementation calls [ScrollActivityDelegate.setPixels]
|
||||
/// and returns true if the overflow was zero.
|
||||
@ -308,7 +394,20 @@ class BallisticScrollActivity extends ScrollActivity {
|
||||
}
|
||||
}
|
||||
|
||||
/// An activity that animates a scroll view based on animation parameters.
|
||||
///
|
||||
/// For example, a [DrivenScrollActivity] is used to implement
|
||||
/// [ScrollController.animateTo].
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [BallisticScrollActivity], which animates a scroll view based on a
|
||||
/// physics [Simulation].
|
||||
class DrivenScrollActivity extends ScrollActivity {
|
||||
/// Creates an activity that animates a scroll view based on animation
|
||||
/// parameters.
|
||||
///
|
||||
/// All of the parameters must be non-null.
|
||||
DrivenScrollActivity(
|
||||
ScrollActivityDelegate delegate, {
|
||||
@required double from,
|
||||
@ -336,8 +435,15 @@ class DrivenScrollActivity extends ScrollActivity {
|
||||
Completer<Null> _completer;
|
||||
AnimationController _controller;
|
||||
|
||||
/// A [Future] that completes when the activity stops.
|
||||
///
|
||||
/// For example, this [Future] will complete if the animation reaches the end
|
||||
/// or if the user interacts with the scroll view in way that causes the
|
||||
/// animation to stop before it reaches the end.
|
||||
Future<Null> get done => _completer.future;
|
||||
|
||||
/// The velocity at which the scroll offset is currently changing (in logical
|
||||
/// pixels per second).
|
||||
double get velocity => _controller.velocity;
|
||||
|
||||
@override
|
||||
|
@ -8,11 +8,44 @@ import 'package:flutter/rendering.dart';
|
||||
import 'framework.dart';
|
||||
import 'ticker_provider.dart';
|
||||
|
||||
/// An interface that [Scrollable] widgets implement in order to use
|
||||
/// [ScrollPosition].
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [ScrollableState], which is the most common implementation of this
|
||||
/// interface.
|
||||
/// * [ScrollPosition], which uses this interface to communicate with the
|
||||
/// scrollable widget.
|
||||
abstract class ScrollContext {
|
||||
/// The [BuildContext] that should be used when dispatching
|
||||
/// [ScrollNotification]s.
|
||||
///
|
||||
/// This context is typically different that the context of the scrollable
|
||||
/// widget itself. For example, [Scrollable] uses a context outside the
|
||||
/// [Viewport] but inside the widgets created by
|
||||
/// [ScrollBehavior.buildViewportChrome].
|
||||
BuildContext get notificationContext;
|
||||
|
||||
/// A [TickerProvider] to use when animating the scroll position.
|
||||
TickerProvider get vsync;
|
||||
|
||||
/// The direction in which the widget scrolls.
|
||||
AxisDirection get axisDirection;
|
||||
|
||||
/// Whether the contents of the widget should ignore [PointerEvent] inputs.
|
||||
///
|
||||
/// Setting this value to true prevents the use from interacting with the
|
||||
/// contents of the widget with pointer events. The widget itself is still
|
||||
/// interactive.
|
||||
///
|
||||
/// For example, if the scroll position is being driven by an animation, it
|
||||
/// might be appropriate to set this value to ignore pointer events to
|
||||
/// prevent the user from accidentially interacting with the contents of the
|
||||
/// widget as it animates. The user will still be able to touch the widget,
|
||||
/// potentially stopping the animation.
|
||||
void setIgnorePointer(bool value);
|
||||
|
||||
/// Whether the user can drag the widget, for example to initiate a scroll.
|
||||
void setCanDrag(bool value);
|
||||
}
|
||||
|
@ -26,6 +26,11 @@ import 'package:flutter/rendering.dart';
|
||||
/// The above values are also exposed in terms of [extentBefore],
|
||||
/// [extentInside], and [extentAfter], which may be more useful for use cases
|
||||
/// such as scroll bars; for example, see [Scrollbar].
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [FixedScrollMetrics], which is an immutable object that implements this
|
||||
/// interface.
|
||||
abstract class ScrollMetrics {
|
||||
/// Creates a [ScrollMetrics] that has the same properties as this object.
|
||||
///
|
||||
@ -33,16 +38,34 @@ abstract class ScrollMetrics {
|
||||
/// of the current state.
|
||||
ScrollMetrics cloneMetrics() => new FixedScrollMetrics.clone(this);
|
||||
|
||||
/// The minimum in-range value for [pixels].
|
||||
///
|
||||
/// The actual [pixels] value might be [outOfRange].
|
||||
double get minScrollExtent;
|
||||
|
||||
/// The maximum in-range value for [pixels].
|
||||
///
|
||||
/// The actual [pixels] value might be [outOfRange].
|
||||
double get maxScrollExtent;
|
||||
|
||||
/// The current scroll position, in logical pixels along the [axisDirection].
|
||||
double get pixels;
|
||||
|
||||
/// The extent of the viewport along the [axisDirection].
|
||||
double get viewportDimension;
|
||||
|
||||
/// The direction in which the scroll view scrolls.
|
||||
AxisDirection get axisDirection;
|
||||
|
||||
/// The axis in which the scroll view scrolls.
|
||||
Axis get axis => axisDirectionToAxis(axisDirection);
|
||||
|
||||
/// Whether the [pixels] value is outside the [minScrollExtent] and
|
||||
/// [maxScrollExtent].
|
||||
bool get outOfRange => pixels < minScrollExtent || pixels > maxScrollExtent;
|
||||
|
||||
/// Whether the [pixels] value is exactly at the [minScrollExtent] or the
|
||||
/// [maxScrollExtent].
|
||||
bool get atEdge => pixels == minScrollExtent || pixels == maxScrollExtent;
|
||||
|
||||
/// The quantity of content conceptually "above" the currently visible content
|
||||
@ -72,8 +95,12 @@ abstract class ScrollMetrics {
|
||||
}
|
||||
}
|
||||
|
||||
/// An immutable snapshot of values associated with a [Scrollable] viewport.
|
||||
///
|
||||
/// For details, see [ScrollMetrics], which defines this object's interfaces.
|
||||
@immutable
|
||||
class FixedScrollMetrics extends ScrollMetrics {
|
||||
/// Creates an immutable snapshot of values associated with a [Scrollable] viewport.
|
||||
FixedScrollMetrics({
|
||||
@required this.minScrollExtent,
|
||||
@required this.maxScrollExtent,
|
||||
@ -82,6 +109,7 @@ class FixedScrollMetrics extends ScrollMetrics {
|
||||
@required this.axisDirection,
|
||||
});
|
||||
|
||||
/// Creates an immutable snapshot of the given metrics.
|
||||
FixedScrollMetrics.clone(ScrollMetrics parent) :
|
||||
minScrollExtent = parent.minScrollExtent,
|
||||
maxScrollExtent = parent.maxScrollExtent,
|
||||
|
@ -304,7 +304,11 @@ class ScrollPositionWithSingleContext extends ScrollPosition implements ScrollAc
|
||||
/// [ScrollDragController.onDragCanceled] for details.
|
||||
@override
|
||||
Drag drag(DragStartDetails details, VoidCallback onDragCanceled) {
|
||||
final ScrollDragController drag = new ScrollDragController(this, details, onDragCanceled);
|
||||
final ScrollDragController drag = new ScrollDragController(
|
||||
delegate: this,
|
||||
details: details,
|
||||
onDragCanceled: onDragCanceled,
|
||||
);
|
||||
beginActivity(new DragScrollActivity(this, drag));
|
||||
assert(_currentDrag == null);
|
||||
_currentDrag = drag;
|
||||
|
Loading…
x
Reference in New Issue
Block a user