"Fossies" - the Fresh Open Source Software Archive

Member "flutter-1.22.4/packages/flutter/lib/src/rendering/viewport_offset.dart" (13 Nov 2020, 11590 Bytes) of package /linux/misc/flutter-1.22.4.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Dart source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 // Copyright 2014 The Flutter Authors. All rights reserved.
    2 // Use of this source code is governed by a BSD-style license that can be
    3 // found in the LICENSE file.
    4 
    5 import 'dart:async';
    6 
    7 import 'package:flutter/animation.dart';
    8 import 'package:flutter/foundation.dart';
    9 
   10 /// The direction of a scroll, relative to the positive scroll offset axis given
   11 /// by an [AxisDirection] and a [GrowthDirection].
   12 ///
   13 /// This contrasts to [GrowthDirection] in that it has a third value, [idle],
   14 /// for the case where no scroll is occurring.
   15 ///
   16 /// This is used by [RenderSliverFloatingPersistentHeader] to only expand when
   17 /// the user is scrolling in the same direction as the detected scroll offset
   18 /// change.
   19 enum ScrollDirection {
   20   /// No scrolling is underway.
   21   idle,
   22 
   23   /// Scrolling is happening in the positive scroll offset direction.
   24   ///
   25   /// For example, for the [GrowthDirection.forward] part of a vertical
   26   /// [AxisDirection.down] list, this means the content is moving up, exposing
   27   /// lower content.
   28   forward,
   29 
   30   /// Scrolling is happening in the negative scroll offset direction.
   31   ///
   32   /// For example, for the [GrowthDirection.forward] part of a vertical
   33   /// [AxisDirection.down] list, this means the content is moving down, exposing
   34   /// earlier content.
   35   reverse,
   36 }
   37 
   38 /// Returns the opposite of the given [ScrollDirection].
   39 ///
   40 /// Specifically, returns [ScrollDirection.reverse] for [ScrollDirection.forward]
   41 /// (and vice versa) and returns [ScrollDirection.idle] for
   42 /// [ScrollDirection.idle].
   43 ScrollDirection flipScrollDirection(ScrollDirection direction) {
   44   switch (direction) {
   45     case ScrollDirection.idle:
   46       return ScrollDirection.idle;
   47     case ScrollDirection.forward:
   48       return ScrollDirection.reverse;
   49     case ScrollDirection.reverse:
   50       return ScrollDirection.forward;
   51   }
   52 }
   53 
   54 /// Which part of the content inside the viewport should be visible.
   55 ///
   56 /// The [pixels] value determines the scroll offset that the viewport uses to
   57 /// select which part of its content to display. As the user scrolls the
   58 /// viewport, this value changes, which changes the content that is displayed.
   59 ///
   60 /// This object is a [Listenable] that notifies its listeners when [pixels]
   61 /// changes.
   62 ///
   63 /// See also:
   64 ///
   65 ///  * [ScrollPosition], which is a commonly used concrete subclass.
   66 ///  * [RenderViewportBase], which is a render object that uses viewport
   67 ///    offsets.
   68 abstract class ViewportOffset extends ChangeNotifier {
   69   /// Default constructor.
   70   ///
   71   /// Allows subclasses to construct this object directly.
   72   ViewportOffset();
   73 
   74   /// Creates a viewport offset with the given [pixels] value.
   75   ///
   76   /// The [pixels] value does not change unless the viewport issues a
   77   /// correction.
   78   factory ViewportOffset.fixed(double value) = _FixedViewportOffset;
   79 
   80   /// Creates a viewport offset with a [pixels] value of 0.0.
   81   ///
   82   /// The [pixels] value does not change unless the viewport issues a
   83   /// correction.
   84   factory ViewportOffset.zero() = _FixedViewportOffset.zero;
   85 
   86   /// The number of pixels to offset the children in the opposite of the axis direction.
   87   ///
   88   /// For example, if the axis direction is down, then the pixel value
   89   /// represents the number of logical pixels to move the children _up_ the
   90   /// screen. Similarly, if the axis direction is left, then the pixels value
   91   /// represents the number of logical pixels to move the children to _right_.
   92   ///
   93   /// This object notifies its listeners when this value changes (except when
   94   /// the value changes due to [correctBy]).
   95   double get pixels;
   96 
   97   /// Called when the viewport's extents are established.
   98   ///
   99   /// The argument is the dimension of the [RenderViewport] in the main axis
  100   /// (e.g. the height, for a vertical viewport).
  101   ///
  102   /// This may be called redundantly, with the same value, each frame. This is
  103   /// called during layout for the [RenderViewport]. If the viewport is
  104   /// configured to shrink-wrap its contents, it may be called several times,
  105   /// since the layout is repeated each time the scroll offset is corrected.
  106   ///
  107   /// If this is called, it is called before [applyContentDimensions]. If this
  108   /// is called, [applyContentDimensions] will be called soon afterwards in the
  109   /// same layout phase. If the viewport is not configured to shrink-wrap its
  110   /// contents, then this will only be called when the viewport recomputes its
  111   /// size (i.e. when its parent lays out), and not during normal scrolling.
  112   ///
  113   /// If applying the viewport dimensions changes the scroll offset, return
  114   /// false. Otherwise, return true. If you return false, the [RenderViewport]
  115   /// will be laid out again with the new scroll offset. This is expensive. (The
  116   /// return value is answering the question "did you accept these viewport
  117   /// dimensions unconditionally?"; if the new dimensions change the
  118   /// [ViewportOffset]'s actual [pixels] value, then the viewport will need to
  119   /// be laid out again.)
  120   bool applyViewportDimension(double viewportDimension);
  121 
  122   /// Called when the viewport's content extents are established.
  123   ///
  124   /// The arguments are the minimum and maximum scroll extents respectively. The
  125   /// minimum will be equal to or less than the maximum. In the case of slivers,
  126   /// the minimum will be equal to or less than zero, the maximum will be equal
  127   /// to or greater than zero.
  128   ///
  129   /// The maximum scroll extent has the viewport dimension subtracted from it.
  130   /// For instance, if there is 100.0 pixels of scrollable content, and the
  131   /// viewport is 80.0 pixels high, then the minimum scroll extent will
  132   /// typically be 0.0 and the maximum scroll extent will typically be 20.0,
  133   /// because there's only 20.0 pixels of actual scroll slack.
  134   ///
  135   /// If applying the content dimensions changes the scroll offset, return
  136   /// false. Otherwise, return true. If you return false, the [RenderViewport]
  137   /// will be laid out again with the new scroll offset. This is expensive. (The
  138   /// return value is answering the question "did you accept these content
  139   /// dimensions unconditionally?"; if the new dimensions change the
  140   /// [ViewportOffset]'s actual [pixels] value, then the viewport will need to
  141   /// be laid out again.)
  142   ///
  143   /// This is called at least once each time the [RenderViewport] is laid out,
  144   /// even if the values have not changed. It may be called many times if the
  145   /// scroll offset is corrected (if this returns false). This is always called
  146   /// after [applyViewportDimension], if that method is called.
  147   bool applyContentDimensions(double minScrollExtent, double maxScrollExtent);
  148 
  149   /// Apply a layout-time correction to the scroll offset.
  150   ///
  151   /// This method should change the [pixels] value by `correction`, but without
  152   /// calling [notifyListeners]. It is called during layout by the
  153   /// [RenderViewport], before [applyContentDimensions]. After this method is
  154   /// called, the layout will be recomputed and that may result in this method
  155   /// being called again, though this should be very rare.
  156   ///
  157   /// See also:
  158   ///
  159   ///  * [jumpTo], for also changing the scroll position when not in layout.
  160   ///    [jumpTo] applies the change immediately and notifies its listeners.
  161   void correctBy(double correction);
  162 
  163   /// Jumps [pixels] from its current value to the given value,
  164   /// without animation, and without checking if the new value is in range.
  165   ///
  166   /// See also:
  167   ///
  168   ///  * [correctBy], for changing the current offset in the middle of layout
  169   ///    and that defers the notification of its listeners until after layout.
  170   void jumpTo(double pixels);
  171 
  172   /// Animates [pixels] from its current value to the given value.
  173   ///
  174   /// The returned [Future] will complete when the animation ends, whether it
  175   /// completed successfully or whether it was interrupted prematurely.
  176   ///
  177   /// The duration must not be zero. To jump to a particular value without an
  178   /// animation, use [jumpTo].
  179   Future<void> animateTo(
  180     double to, {
  181     required Duration duration,
  182     required Curve curve,
  183   });
  184 
  185   /// Calls [jumpTo] if duration is null or [Duration.zero], otherwise
  186   /// [animateTo] is called.
  187   ///
  188   /// If [animateTo] is called then [curve] defaults to [Curves.ease]. The
  189   /// [clamp] parameter is ignored by this stub implementation but subclasses
  190   /// like [ScrollPosition] handle it by adjusting [to] to prevent over or
  191   /// underscroll.
  192   Future<void> moveTo(
  193     double to, {
  194     Duration? duration,
  195     Curve? curve,
  196     bool? clamp,
  197   }) {
  198     assert(to != null);
  199     if (duration == null || duration == Duration.zero) {
  200       jumpTo(to);
  201       return Future<void>.value();
  202     } else {
  203       return animateTo(to, duration: duration, curve: curve ?? Curves.ease);
  204     }
  205   }
  206 
  207   /// The direction in which the user is trying to change [pixels], relative to
  208   /// the viewport's [RenderViewportBase.axisDirection].
  209   ///
  210   /// If the _user_ is not scrolling, this will return [ScrollDirection.idle]
  211   /// even if there is (for example) a [ScrollActivity] currently animating the
  212   /// position.
  213   ///
  214   /// This is exposed in [SliverConstraints.userScrollDirection], which is used
  215   /// by some slivers to determine how to react to a change in scroll offset.
  216   /// For example, [RenderSliverFloatingPersistentHeader] will only expand a
  217   /// floating app bar when the [userScrollDirection] is in the positive scroll
  218   /// offset direction.
  219   ScrollDirection get userScrollDirection;
  220 
  221   /// Whether a viewport is allowed to change [pixels] implicitly to respond to
  222   /// a call to [RenderObject.showOnScreen].
  223   ///
  224   /// [RenderObject.showOnScreen] is for example used to bring a text field
  225   /// fully on screen after it has received focus. This property controls
  226   /// whether the viewport associated with this offset is allowed to change the
  227   /// offset's [pixels] value to fulfill such a request.
  228   bool get allowImplicitScrolling;
  229 
  230   @override
  231   String toString() {
  232     final List<String> description = <String>[];
  233     debugFillDescription(description);
  234     return '${describeIdentity(this)}(${description.join(", ")})';
  235   }
  236 
  237   /// Add additional information to the given description for use by [toString].
  238   ///
  239   /// This method makes it easier for subclasses to coordinate to provide a
  240   /// high-quality [toString] implementation. The [toString] implementation on
  241   /// the [State] base class calls [debugFillDescription] to collect useful
  242   /// information from subclasses to incorporate into its return value.
  243   ///
  244   /// If you override this, make sure to start your method with a call to
  245   /// `super.debugFillDescription(description)`.
  246   @mustCallSuper
  247   void debugFillDescription(List<String> description) {
  248     description.add('offset: ${pixels.toStringAsFixed(1)}');
  249   }
  250 }
  251 
  252 class _FixedViewportOffset extends ViewportOffset {
  253   _FixedViewportOffset(this._pixels);
  254   _FixedViewportOffset.zero() : _pixels = 0.0;
  255 
  256   double _pixels;
  257 
  258   @override
  259   double get pixels => _pixels;
  260 
  261   @override
  262   bool applyViewportDimension(double viewportDimension) => true;
  263 
  264   @override
  265   bool applyContentDimensions(double minScrollExtent, double maxScrollExtent) => true;
  266 
  267   @override
  268   void correctBy(double correction) {
  269     _pixels += correction;
  270   }
  271 
  272   @override
  273   void jumpTo(double pixels) {
  274     // Do nothing, viewport is fixed.
  275   }
  276 
  277   @override
  278   Future<void> animateTo(
  279     double to, {
  280     required Duration duration,
  281     required Curve curve,
  282   }) async { }
  283 
  284   @override
  285   ScrollDirection get userScrollDirection => ScrollDirection.idle;
  286 
  287   @override
  288   bool get allowImplicitScrolling => false;
  289 }