-
Notifications
You must be signed in to change notification settings - Fork 30.9k
Expand file tree
/
Copy pathscroll_metrics.dart
More file actions
225 lines (194 loc) · 8.26 KB
/
Copy pathscroll_metrics.dart
File metadata and controls
225 lines (194 loc) · 8.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/// @docImport 'dart:ui';
/// @docImport 'package:flutter/material.dart';
///
/// @docImport 'scroll_position.dart';
/// @docImport 'scrollable.dart';
/// @docImport 'viewport.dart';
library;
import 'dart:math' as math;
import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';
/// A description of a [Scrollable]'s contents, useful for modeling the state
/// 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].
///
/// {@tool dartpad}
/// This sample shows how a [ScrollMetricsNotification] is dispatched when
/// the [ScrollMetrics] changed as a result of resizing the [Viewport].
/// Press the floating action button to increase the scrollable window's size.
///
/// ** See code in examples/api/lib/widgets/scroll_position/scroll_metrics_notification.0.dart **
/// {@end-tool}
///
/// See also:
///
/// * [FixedScrollMetrics], which is an immutable object that implements this
/// interface.
mixin 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.
///
/// The named arguments allow the values to be adjusted in the process. This
/// is useful to examine hypothetical situations, for example "would applying
/// this delta unmodified take the position [outOfRange]?".
ScrollMetrics copyWith({
double? minScrollExtent,
double? maxScrollExtent,
double? pixels,
double? viewportDimension,
AxisDirection? axisDirection,
double? devicePixelRatio,
}) {
return FixedScrollMetrics(
minScrollExtent: minScrollExtent ?? (hasContentDimensions ? this.minScrollExtent : null),
maxScrollExtent: maxScrollExtent ?? (hasContentDimensions ? this.maxScrollExtent : null),
pixels: pixels ?? (hasPixels ? this.pixels : null),
viewportDimension:
viewportDimension ?? (hasViewportDimension ? this.viewportDimension : null),
axisDirection: axisDirection ?? this.axisDirection,
devicePixelRatio: devicePixelRatio ?? this.devicePixelRatio,
);
}
/// The minimum in-range value for [pixels].
///
/// The actual [pixels] value might be [outOfRange].
///
/// This value is typically less than or equal to
/// [maxScrollExtent]. It can be negative infinity, if the scroll is unbounded.
double get minScrollExtent;
/// The maximum in-range value for [pixels].
///
/// The actual [pixels] value might be [outOfRange].
///
/// This value is typically greater than or equal to
/// [minScrollExtent]. It can be infinity, if the scroll is unbounded.
///
/// For scrollables that lazily construct their contents, such as
/// [ListView.builder], this value can be an estimate that changes as more
/// children are laid out.
double get maxScrollExtent;
/// Whether the [minScrollExtent] and the [maxScrollExtent] properties are available.
bool get hasContentDimensions;
/// The current scroll position, in logical pixels along the [axisDirection].
double get pixels;
/// Whether the [pixels] property is available.
bool get hasPixels;
/// The extent of the viewport along the [axisDirection].
double get viewportDimension;
/// Whether the [viewportDimension] property is available.
bool get hasViewportDimension;
/// 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 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 content conceptually "inside" the viewport in the
/// scrollable (including empty space if the total amount of content is less
/// than the [viewportDimension]).
///
/// The value is typically the extent of the viewport ([viewportDimension])
/// when [outOfRange] is false. It can be less when overscrolling.
///
/// The value is always non-negative, and less than or equal to [viewportDimension].
double get extentInside {
assert(minScrollExtent <= maxScrollExtent);
return viewportDimension
// "above" overscroll value
-
clampDouble(minScrollExtent - pixels, 0, viewportDimension)
// "below" overscroll value
-
clampDouble(pixels - maxScrollExtent, 0, viewportDimension);
}
/// The quantity of content conceptually "below" the viewport in the scrollable.
/// This is the content below the content described by [extentInside].
double get extentAfter => math.max(maxScrollExtent - pixels, 0.0);
/// The total quantity of content available.
///
/// This is the sum of [extentBefore], [extentInside], and [extentAfter], modulo
/// any rounding errors.
double get extentTotal => maxScrollExtent - minScrollExtent + viewportDimension;
/// The [FlutterView.devicePixelRatio] of the view that the [Scrollable]
/// associated with this metrics object is drawn into.
double get devicePixelRatio;
}
/// An immutable snapshot of values associated with a [Scrollable] viewport.
///
/// For details, see [ScrollMetrics], which defines this object's interfaces.
///
/// {@tool dartpad}
/// This sample shows how a [ScrollMetricsNotification] is dispatched when
/// the [ScrollMetrics] changed as a result of resizing the [Viewport].
/// Press the floating action button to increase the scrollable window's size.
///
/// ** See code in examples/api/lib/widgets/scroll_position/scroll_metrics_notification.0.dart **
/// {@end-tool}
class FixedScrollMetrics with ScrollMetrics {
/// Creates an immutable snapshot of values associated with a [Scrollable] viewport.
FixedScrollMetrics({
required double? minScrollExtent,
required double? maxScrollExtent,
required double? pixels,
required double? viewportDimension,
required this.axisDirection,
required this.devicePixelRatio,
}) : _minScrollExtent = minScrollExtent,
_maxScrollExtent = maxScrollExtent,
_pixels = pixels,
_viewportDimension = viewportDimension;
@override
double get minScrollExtent => _minScrollExtent!;
final double? _minScrollExtent;
@override
double get maxScrollExtent => _maxScrollExtent!;
final double? _maxScrollExtent;
@override
bool get hasContentDimensions => _minScrollExtent != null && _maxScrollExtent != null;
@override
double get pixels => _pixels!;
final double? _pixels;
@override
bool get hasPixels => _pixels != null;
@override
double get viewportDimension => _viewportDimension!;
final double? _viewportDimension;
@override
bool get hasViewportDimension => _viewportDimension != null;
@override
final AxisDirection axisDirection;
@override
final double devicePixelRatio;
@override
String toString() {
return '${objectRuntimeType(this, 'FixedScrollMetrics')}(${extentBefore.toStringAsFixed(1)}..[${extentInside.toStringAsFixed(1)}]..${extentAfter.toStringAsFixed(1)})';
}
}