scroll_metrics.dart 4.76 KB
Newer Older
1 2 3 4 5 6 7 8 9
// Copyright 2016 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:math' as math;

import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';

10
/// A description of a [Scrollable]'s contents, useful for modeling the state
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
/// of its viewport.
///
/// This class defines a current position, [pixels], and a range of values
/// considered "in bounds" for that position. The range has a minimum value at
/// [minScrollExtent] and a maximum value at [maxScrollExtent] (inclusive). The
/// viewport scrolls in the direction and axis described by [axisDirection]
/// and [axis].
///
/// The [outOfRange] getter will return true if [pixels] is outside this defined
/// range. The [atEdge] getter will return true if the [pixels] position equals
/// either the [minScrollExtent] or the [maxScrollExtent].
///
/// The dimensions of the viewport in the given [axis] are described by
/// [viewportDimension].
///
/// 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].
29 30 31 32 33
///
/// See also:
///
///  * [FixedScrollMetrics], which is an immutable object that implements this
///    interface.
34 35 36 37 38 39 40
abstract class ScrollMetrics {
  /// Creates a [ScrollMetrics] that has the same properties as this object.
  ///
  /// This is useful if this object is mutable, but you want to get a snapshot
  /// of the current state.
  ScrollMetrics cloneMetrics() => new FixedScrollMetrics.clone(this);

41 42 43
  /// The minimum in-range value for [pixels].
  ///
  /// The actual [pixels] value might be [outOfRange].
44
  double get minScrollExtent;
45 46 47 48

  /// The maximum in-range value for [pixels].
  ///
  /// The actual [pixels] value might be [outOfRange].
49
  double get maxScrollExtent;
50 51

  /// The current scroll position, in logical pixels along the [axisDirection].
52
  double get pixels;
53 54

  /// The extent of the viewport along the [axisDirection].
55
  double get viewportDimension;
56 57

  /// The direction in which the scroll view scrolls.
58 59
  AxisDirection get axisDirection;

60
  /// The axis in which the scroll view scrolls.
61 62
  Axis get axis => axisDirectionToAxis(axisDirection);

63 64
  /// Whether the [pixels] value is outside the [minScrollExtent] and
  /// [maxScrollExtent].
65 66
  bool get outOfRange => pixels < minScrollExtent || pixels > maxScrollExtent;

67 68
  /// Whether the [pixels] value is exactly at the [minScrollExtent] or the
  /// [maxScrollExtent].
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
  bool get atEdge => pixels == minScrollExtent || pixels == maxScrollExtent;

  /// The quantity of content conceptually "above" the currently visible content
  /// of the viewport in the scrollable. This is the content above the content
  /// described by [extentInside].
  double get extentBefore => math.max(pixels - minScrollExtent, 0.0);

  /// The quantity of visible content.
  ///
  /// If [extentBefore] and [extentAfter] are non-zero, then this is typically
  /// the height of the viewport. It could be less if there is less content
  /// visible than the size of the viewport.
  double get extentInside {
    return math.min(pixels, maxScrollExtent) -
           math.max(pixels, minScrollExtent) +
           math.min(viewportDimension, maxScrollExtent - minScrollExtent);
  }

  /// The quantity of content conceptually "below" the currently visible content
  /// of the viewport in the scrollable. This is the content below the content
  /// described by [extentInside].
  double get extentAfter => math.max(maxScrollExtent - pixels, 0.0);
}

93 94 95
/// An immutable snapshot of values associated with a [Scrollable] viewport.
///
/// For details, see [ScrollMetrics], which defines this object's interfaces.
96 97
@immutable
class FixedScrollMetrics extends ScrollMetrics {
98
  /// Creates an immutable snapshot of values associated with a [Scrollable] viewport.
99 100 101 102 103 104 105 106
  FixedScrollMetrics({
    @required this.minScrollExtent,
    @required this.maxScrollExtent,
    @required this.pixels,
    @required this.viewportDimension,
    @required this.axisDirection,
  });

107
  /// Creates an immutable snapshot of the given metrics.
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
  FixedScrollMetrics.clone(ScrollMetrics parent) :
    minScrollExtent = parent.minScrollExtent,
    maxScrollExtent = parent.maxScrollExtent,
    pixels = parent.pixels,
    viewportDimension = parent.viewportDimension,
    axisDirection = parent.axisDirection;

  @override
  final double minScrollExtent;

  @override
  final double maxScrollExtent;

  @override
  final double pixels;

  @override
  final double viewportDimension;

  @override
  final AxisDirection axisDirection;
129 130 131 132 133

  @override
  String toString() {
    return '$runtimeType(${extentBefore.toStringAsFixed(1)}..[${extentInside.toStringAsFixed(1)}]..${extentAfter.toStringAsFixed(1)})';
  }
134
}