Unverified Commit b972f872 authored by Kate Lovett's avatar Kate Lovett Committed by GitHub

Clean up ScrollbarPainter (#107179)

parent c4aea1c3
...@@ -283,6 +283,7 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter { ...@@ -283,6 +283,7 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter {
_shape = value; _shape = value;
notifyListeners(); notifyListeners();
} }
/// The amount of space by which to inset the scrollbar's start and end, as /// The amount of space by which to inset the scrollbar's start and end, as
/// well as its side to the nearest edge, in logical pixels. /// well as its side to the nearest edge, in logical pixels.
/// ///
...@@ -304,7 +305,6 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter { ...@@ -304,7 +305,6 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter {
notifyListeners(); notifyListeners();
} }
/// The preferred smallest size the scrollbar thumb can shrink to when the total /// The preferred smallest size the scrollbar thumb can shrink to when the total
/// scrollable extent is large, the current visible viewport is small, and the /// scrollable extent is large, the current visible viewport is small, and the
/// viewport is not overscrolled. /// viewport is not overscrolled.
...@@ -391,23 +391,129 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter { ...@@ -391,23 +391,129 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter {
notifyListeners(); notifyListeners();
} }
void _debugAssertIsValidOrientation(ScrollbarOrientation orientation) { // - Scrollbar Details
assert(
(_isVertical && _isVerticalOrientation(orientation)) || (!_isVertical && !_isVerticalOrientation(orientation)), Rect? _trackRect;
'The given ScrollbarOrientation: $orientation is incompatible with the current AxisDirection: $_lastAxisDirection.' // The full painted length of the track
double get _trackExtent => _lastMetrics!.viewportDimension - _totalTrackMainAxisOffsets;
// The full length of the track that the thumb can travel
double get _traversableTrackExtent => _trackExtent - (2 * mainAxisMargin);
// Track Offsets
// The track is offset by only padding.
double get _totalTrackMainAxisOffsets => _isVertical ? padding.vertical : padding.horizontal;
double get _leadingTrackMainAxisOffset {
switch(_resolvedOrientation) {
case ScrollbarOrientation.left:
case ScrollbarOrientation.right:
return padding.top;
case ScrollbarOrientation.top:
case ScrollbarOrientation.bottom:
return padding.left;
}
}
Rect? _thumbRect;
// The current scroll position + _leadingThumbMainAxisOffset
late double _thumbOffset;
// The fraction visible in relation to the trversable length of the track.
late double _thumbExtent;
// Thumb Offsets
// The thumb is offset by padding and margins.
double get _leadingThumbMainAxisOffset {
switch(_resolvedOrientation) {
case ScrollbarOrientation.left:
case ScrollbarOrientation.right:
return padding.top + mainAxisMargin;
case ScrollbarOrientation.top:
case ScrollbarOrientation.bottom:
return padding.left + mainAxisMargin;
}
}
void _setThumbExtent() {
// Thumb extent reflects fraction of content visible, as long as this
// isn't less than the absolute minimum size.
// _totalContentExtent >= viewportDimension, so (_totalContentExtent - _mainAxisPadding) > 0
final double fractionVisible = clampDouble(
(_lastMetrics!.extentInside - _totalTrackMainAxisOffsets)
/ (_totalContentExtent - _totalTrackMainAxisOffsets),
0.0,
1.0,
); );
final double thumbExtent = math.max(
math.min(_traversableTrackExtent, minOverscrollLength),
_traversableTrackExtent * fractionVisible,
);
final double fractionOverscrolled = 1.0 - _lastMetrics!.extentInside / _lastMetrics!.viewportDimension;
final double safeMinLength = math.min(minLength, _traversableTrackExtent);
final double newMinLength = (_beforeExtent > 0 && _afterExtent > 0)
// Thumb extent is no smaller than minLength if scrolling normally.
? safeMinLength
// User is overscrolling. Thumb extent can be less than minLength
// but no smaller than minOverscrollLength. We can't use the
// fractionVisible to produce intermediate values between minLength and
// minOverscrollLength when the user is transitioning from regular
// scrolling to overscrolling, so we instead use the percentage of the
// content that is still in the viewport to determine the size of the
// thumb. iOS behavior appears to have the thumb reach its minimum size
// with ~20% of overscroll. We map the percentage of minLength from
// [0.8, 1.0] to [0.0, 1.0], so 0% to 20% of overscroll will produce
// values for the thumb that range between minLength and the smallest
// possible value, minOverscrollLength.
: safeMinLength * (1.0 - clampDouble(fractionOverscrolled, 0.0, 0.2) / 0.2);
// The `thumbExtent` should be no greater than `trackSize`, otherwise
// the scrollbar may scroll towards the wrong direction.
_thumbExtent = clampDouble(thumbExtent, newMinLength, _traversableTrackExtent);
} }
/// Check whether given scrollbar orientation is vertical // - Scrollable Details
bool _isVerticalOrientation(ScrollbarOrientation orientation) =>
orientation == ScrollbarOrientation.left
|| orientation == ScrollbarOrientation.right;
ScrollMetrics? _lastMetrics; ScrollMetrics? _lastMetrics;
bool get _lastMetricsAreScrollable => _lastMetrics!.minScrollExtent != _lastMetrics!.maxScrollExtent;
AxisDirection? _lastAxisDirection; AxisDirection? _lastAxisDirection;
Rect? _thumbRect;
Rect? _trackRect; bool get _isVertical => _lastAxisDirection == AxisDirection.down || _lastAxisDirection == AxisDirection.up;
late double _thumbOffset; bool get _isReversed => _lastAxisDirection == AxisDirection.up || _lastAxisDirection == AxisDirection.left;
// The amount of scroll distance before and after the current position.
double get _beforeExtent => _isReversed ? _lastMetrics!.extentAfter : _lastMetrics!.extentBefore;
double get _afterExtent => _isReversed ? _lastMetrics!.extentBefore : _lastMetrics!.extentAfter;
// The total size of the scrollable content.
double get _totalContentExtent {
return _lastMetrics!.maxScrollExtent
- _lastMetrics!.minScrollExtent
+ _lastMetrics!.viewportDimension;
}
ScrollbarOrientation get _resolvedOrientation {
if (scrollbarOrientation == null) {
if (_isVertical) {
return textDirection == TextDirection.ltr
? ScrollbarOrientation.right
: ScrollbarOrientation.left;
}
return ScrollbarOrientation.bottom;
}
return scrollbarOrientation!;
}
void _debugAssertIsValidOrientation(ScrollbarOrientation orientation) {
assert(
() {
bool isVerticalOrientation(ScrollbarOrientation orientation) =>
orientation == ScrollbarOrientation.left
|| orientation == ScrollbarOrientation.right;
return (_isVertical && isVerticalOrientation(orientation))
|| (!_isVertical && !isVerticalOrientation(orientation));
}(),
'The given ScrollbarOrientation: $orientation is incompatible with the '
'current AxisDirection: $_lastAxisDirection.'
);
}
// - Updating
/// Update with new [ScrollMetrics]. If the metrics change, the scrollbar will /// Update with new [ScrollMetrics]. If the metrics change, the scrollbar will
/// show and redraw itself based on these new metrics. /// show and redraw itself based on these new metrics.
...@@ -433,7 +539,6 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter { ...@@ -433,7 +539,6 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter {
if (!needPaint(oldMetrics) && !needPaint(metrics)) { if (!needPaint(oldMetrics) && !needPaint(metrics)) {
return; return;
} }
notifyListeners(); notifyListeners();
} }
...@@ -443,6 +548,8 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter { ...@@ -443,6 +548,8 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter {
radius = nextRadius; radius = nextRadius;
} }
// - Painting
Paint get _paintThumb { Paint get _paintThumb {
return Paint() return Paint()
..color = color.withOpacity(color.opacity * fadeoutOpacityAnimation.value); ..color = color.withOpacity(color.opacity * fadeoutOpacityAnimation.value);
...@@ -459,67 +566,50 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter { ...@@ -459,67 +566,50 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter {
..color = trackColor.withOpacity(trackColor.opacity * fadeoutOpacityAnimation.value); ..color = trackColor.withOpacity(trackColor.opacity * fadeoutOpacityAnimation.value);
} }
void _paintScrollbar(Canvas canvas, Size size, double thumbExtent, AxisDirection direction) { void _paintScrollbar(Canvas canvas, Size size) {
assert( assert(
textDirection != null, textDirection != null,
'A TextDirection must be provided before a Scrollbar can be painted.', 'A TextDirection must be provided before a Scrollbar can be painted.',
); );
final ScrollbarOrientation resolvedOrientation;
if (scrollbarOrientation == null) {
if (_isVertical) {
resolvedOrientation = textDirection == TextDirection.ltr
? ScrollbarOrientation.right
: ScrollbarOrientation.left;
} else {
resolvedOrientation = ScrollbarOrientation.bottom;
}
}
else {
resolvedOrientation = scrollbarOrientation!;
}
final double x, y; final double x, y;
final Size thumbSize, trackSize; final Size thumbSize, trackSize;
final Offset trackOffset, borderStart, borderEnd; final Offset trackOffset, borderStart, borderEnd;
_debugAssertIsValidOrientation(_resolvedOrientation);
_debugAssertIsValidOrientation(resolvedOrientation); switch(_resolvedOrientation) {
switch(resolvedOrientation) {
case ScrollbarOrientation.left: case ScrollbarOrientation.left:
thumbSize = Size(thickness, thumbExtent); thumbSize = Size(thickness, _thumbExtent);
trackSize = Size(thickness + 2 * crossAxisMargin, _trackExtent); trackSize = Size(thickness + 2 * crossAxisMargin, _trackExtent);
x = crossAxisMargin + padding.left; x = crossAxisMargin + padding.left;
y = _thumbOffset; y = _thumbOffset;
trackOffset = Offset(x - crossAxisMargin, padding.top); trackOffset = Offset(x - crossAxisMargin, _leadingTrackMainAxisOffset);
borderStart = trackOffset + Offset(trackSize.width, 0.0); borderStart = trackOffset + Offset(trackSize.width, 0.0);
borderEnd = Offset(trackOffset.dx + trackSize.width, trackOffset.dy + _trackExtent); borderEnd = Offset(trackOffset.dx + trackSize.width, trackOffset.dy + _trackExtent);
break; break;
case ScrollbarOrientation.right: case ScrollbarOrientation.right:
thumbSize = Size(thickness, thumbExtent); thumbSize = Size(thickness, _thumbExtent);
trackSize = Size(thickness + 2 * crossAxisMargin, _trackExtent); trackSize = Size(thickness + 2 * crossAxisMargin, _trackExtent);
x = size.width - thickness - crossAxisMargin - padding.right; x = size.width - thickness - crossAxisMargin - padding.right;
y = _thumbOffset; y = _thumbOffset;
trackOffset = Offset(x - crossAxisMargin, padding.top); trackOffset = Offset(x - crossAxisMargin, _leadingTrackMainAxisOffset);
borderStart = trackOffset; borderStart = trackOffset;
borderEnd = Offset(trackOffset.dx, trackOffset.dy + _trackExtent); borderEnd = Offset(trackOffset.dx, trackOffset.dy + _trackExtent);
break; break;
case ScrollbarOrientation.top: case ScrollbarOrientation.top:
thumbSize = Size(thumbExtent, thickness); thumbSize = Size(_thumbExtent, thickness);
trackSize = Size(_trackExtent, thickness + 2 * crossAxisMargin); trackSize = Size(_trackExtent, thickness + 2 * crossAxisMargin);
x = _thumbOffset; x = _thumbOffset;
y = crossAxisMargin + padding.top; y = crossAxisMargin + padding.top;
trackOffset = Offset(padding.left, y - crossAxisMargin); trackOffset = Offset(_leadingTrackMainAxisOffset, y - crossAxisMargin);
borderStart = trackOffset + Offset(0.0, trackSize.height); borderStart = trackOffset + Offset(0.0, trackSize.height);
borderEnd = Offset(trackOffset.dx + _trackExtent, trackOffset.dy + trackSize.height); borderEnd = Offset(trackOffset.dx + _trackExtent, trackOffset.dy + trackSize.height);
break; break;
case ScrollbarOrientation.bottom: case ScrollbarOrientation.bottom:
thumbSize = Size(thumbExtent, thickness); thumbSize = Size(_thumbExtent, thickness);
trackSize = Size(_trackExtent, thickness + 2 * crossAxisMargin); trackSize = Size(_trackExtent, thickness + 2 * crossAxisMargin);
x = _thumbOffset; x = _thumbOffset;
y = size.height - thickness - crossAxisMargin - padding.bottom; y = size.height - thickness - crossAxisMargin - padding.bottom;
trackOffset = Offset(padding.left, y - crossAxisMargin); trackOffset = Offset(_leadingTrackMainAxisOffset, y - crossAxisMargin);
borderStart = trackOffset; borderStart = trackOffset;
borderEnd = Offset(trackOffset.dx + _trackExtent, trackOffset.dy); borderEnd = Offset(trackOffset.dx + _trackExtent, trackOffset.dy);
break; break;
...@@ -557,70 +647,33 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter { ...@@ -557,70 +647,33 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter {
} }
} }
double _thumbExtent() {
// Thumb extent reflects fraction of content visible, as long as this
// isn't less than the absolute minimum size.
// _totalContentExtent >= viewportDimension, so (_totalContentExtent - _mainAxisPadding) > 0
final double fractionVisible = clampDouble(
(_lastMetrics!.extentInside - _mainAxisPadding) /
(_totalContentExtent - _mainAxisPadding),
0.0,
1.0);
final double thumbExtent = math.max(
math.min(_traversableTrackExtent, minOverscrollLength),
_traversableTrackExtent * fractionVisible,
);
final double fractionOverscrolled = 1.0 - _lastMetrics!.extentInside / _lastMetrics!.viewportDimension;
final double safeMinLength = math.min(minLength, _traversableTrackExtent);
final double newMinLength = (_beforeExtent > 0 && _afterExtent > 0)
// Thumb extent is no smaller than minLength if scrolling normally.
? safeMinLength
// User is overscrolling. Thumb extent can be less than minLength
// but no smaller than minOverscrollLength. We can't use the
// fractionVisible to produce intermediate values between minLength and
// minOverscrollLength when the user is transitioning from regular
// scrolling to overscrolling, so we instead use the percentage of the
// content that is still in the viewport to determine the size of the
// thumb. iOS behavior appears to have the thumb reach its minimum size
// with ~20% of overscroll. We map the percentage of minLength from
// [0.8, 1.0] to [0.0, 1.0], so 0% to 20% of overscroll will produce
// values for the thumb that range between minLength and the smallest
// possible value, minOverscrollLength.
: safeMinLength * (1.0 - clampDouble(fractionOverscrolled, 0.0, 0.2) / 0.2);
// The `thumbExtent` should be no greater than `trackSize`, otherwise
// the scrollbar may scroll towards the wrong direction.
final double extent = clampDouble(thumbExtent, newMinLength, _traversableTrackExtent);
return extent;
}
@override @override
void dispose() { void paint(Canvas canvas, Size size) {
fadeoutOpacityAnimation.removeListener(notifyListeners); if (_lastAxisDirection == null
super.dispose(); || _lastMetrics == null
|| _lastMetrics!.maxScrollExtent <= _lastMetrics!.minScrollExtent) {
return;
}
// Skip painting if there's not enough space.
if (_traversableTrackExtent <= 0) {
return;
}
// Do not paint a scrollbar if the scroll view is infinitely long.
// TODO(Piinks): Special handling for infinite scroll views,
// https://github.com/flutter/flutter/issues/41434
if (_lastMetrics!.maxScrollExtent.isInfinite) {
return;
} }
bool get _isVertical => _lastAxisDirection == AxisDirection.down || _lastAxisDirection == AxisDirection.up; _setThumbExtent();
bool get _isReversed => _lastAxisDirection == AxisDirection.up || _lastAxisDirection == AxisDirection.left; final double thumbPositionOffset = _getScrollToTrack(_lastMetrics!, _thumbExtent);
// The amount of scroll distance before and after the current position. _thumbOffset = thumbPositionOffset + _leadingThumbMainAxisOffset;
double get _beforeExtent => _isReversed ? _lastMetrics!.extentAfter : _lastMetrics!.extentBefore;
double get _afterExtent => _isReversed ? _lastMetrics!.extentBefore : _lastMetrics!.extentAfter;
// Padding of the thumb track.
double get _mainAxisPadding => _isVertical ? padding.vertical : padding.horizontal;
// The length of the painted track.
double get _trackExtent => _lastMetrics!.viewportDimension - _mainAxisPadding;
// The length of the track that is traversable by the thumb.
double get _traversableTrackExtent => _trackExtent - (2 * mainAxisMargin);
// The total size of the scrollable content. return _paintScrollbar(canvas, size);
double get _totalContentExtent {
return _lastMetrics!.maxScrollExtent
- _lastMetrics!.minScrollExtent
+ _lastMetrics!.viewportDimension;
} }
// - Scroll Position Conversion
/// Convert between a thumb track position and the corresponding scroll /// Convert between a thumb track position and the corresponding scroll
/// position. /// position.
/// ///
...@@ -628,7 +681,7 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter { ...@@ -628,7 +681,7 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter {
double getTrackToScroll(double thumbOffsetLocal) { double getTrackToScroll(double thumbOffsetLocal) {
assert(thumbOffsetLocal != null); assert(thumbOffsetLocal != null);
final double scrollableExtent = _lastMetrics!.maxScrollExtent - _lastMetrics!.minScrollExtent; final double scrollableExtent = _lastMetrics!.maxScrollExtent - _lastMetrics!.minScrollExtent;
final double thumbMovableExtent = _traversableTrackExtent - _thumbExtent(); final double thumbMovableExtent = _traversableTrackExtent - _thumbExtent;
return scrollableExtent * thumbOffsetLocal / thumbMovableExtent; return scrollableExtent * thumbOffsetLocal / thumbMovableExtent;
} }
...@@ -645,35 +698,27 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter { ...@@ -645,35 +698,27 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter {
return (_isReversed ? 1 - fractionPast : fractionPast) * (_traversableTrackExtent - thumbExtent); return (_isReversed ? 1 - fractionPast : fractionPast) * (_traversableTrackExtent - thumbExtent);
} }
@override // - Hit Testing
void paint(Canvas canvas, Size size) {
if (_lastAxisDirection == null
|| _lastMetrics == null
|| _lastMetrics!.maxScrollExtent <= _lastMetrics!.minScrollExtent) {
return;
}
// Skip painting if there's not enough space. @override
if (_lastMetrics!.viewportDimension <= _mainAxisPadding || _traversableTrackExtent <= 0) { bool? hitTest(Offset? position) {
return; // There is nothing painted to hit.
if (_thumbRect == null) {
return null;
} }
final double beforePadding = _isVertical ? padding.top : padding.left; // Interaction disabled.
final double thumbExtent = _thumbExtent(); if (ignorePointer
final double thumbOffsetLocal = _getScrollToTrack(_lastMetrics!, thumbExtent); // The thumb is not able to be hit when transparent.
_thumbOffset = thumbOffsetLocal + mainAxisMargin + beforePadding; || fadeoutOpacityAnimation.value == 0.0
// Not scrollable
// Do not paint a scrollbar if the scroll view is infinitely long. || !_lastMetricsAreScrollable) {
// TODO(Piinks): Special handling for infinite scroll views, https://github.com/flutter/flutter/issues/41434 return false;
if (_lastMetrics!.maxScrollExtent.isInfinite) {
return;
} }
return _paintScrollbar(canvas, size, thumbExtent, _lastAxisDirection!); return _trackRect!.contains(position!);
} }
bool get _lastMetricsAreScrollable => _lastMetrics!.minScrollExtent != _lastMetrics!.maxScrollExtent;
/// Same as hitTest, but includes some padding when the [PointerEvent] is /// Same as hitTest, but includes some padding when the [PointerEvent] is
/// caused by [PointerDeviceKind.touch] to make sure that the region /// caused by [PointerDeviceKind.touch] to make sure that the region
/// isn't too small to be interacted with by the user. /// isn't too small to be interacted with by the user.
...@@ -756,28 +801,6 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter { ...@@ -756,28 +801,6 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter {
} }
} }
// Scrollbars are interactive.
@override
bool? hitTest(Offset? position) {
if (_thumbRect == null) {
return null;
}
if (ignorePointer) {
return false;
}
// The thumb is not able to be hit when transparent.
if (fadeoutOpacityAnimation.value == 0.0) {
return false;
}
if (!_lastMetricsAreScrollable) {
return false;
}
return _trackRect!.contains(position!);
}
@override @override
bool shouldRepaint(ScrollbarPainter oldDelegate) { bool shouldRepaint(ScrollbarPainter oldDelegate) {
// Should repaint if any properties changed. // Should repaint if any properties changed.
...@@ -807,6 +830,12 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter { ...@@ -807,6 +830,12 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter {
@override @override
String toString() => describeIdentity(this); String toString() => describeIdentity(this);
@override
void dispose() {
fadeoutOpacityAnimation.removeListener(notifyListeners);
super.dispose();
}
} }
/// An extendable base class for building scrollbars that fade in and out. /// An extendable base class for building scrollbars that fade in and out.
...@@ -1669,7 +1698,7 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv ...@@ -1669,7 +1698,7 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
case TargetPlatform.iOS: case TargetPlatform.iOS:
case TargetPlatform.android: case TargetPlatform.android:
// We can only drag the scrollbar into overscroll on mobile // We can only drag the scrollbar into overscroll on mobile
// platforms, and only if the physics allow it. // platforms, and only then if the physics allow it.
break; break;
} }
position.jumpTo(newPosition); position.jumpTo(newPosition);
...@@ -1908,7 +1937,7 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv ...@@ -1908,7 +1937,7 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
() => _ThumbPressGestureRecognizer( () => _ThumbPressGestureRecognizer(
debugOwner: this, debugOwner: this,
customPaintKey: _scrollbarPainterKey, customPaintKey: _scrollbarPainterKey,
pressDuration: widget.pressDuration, duration: widget.pressDuration,
), ),
(_ThumbPressGestureRecognizer instance) { (_ThumbPressGestureRecognizer instance) {
instance.onLongPress = handleThumbPress; instance.onLongPress = handleThumbPress;
...@@ -2074,11 +2103,8 @@ class _ThumbPressGestureRecognizer extends LongPressGestureRecognizer { ...@@ -2074,11 +2103,8 @@ class _ThumbPressGestureRecognizer extends LongPressGestureRecognizer {
_ThumbPressGestureRecognizer({ _ThumbPressGestureRecognizer({
required Object super.debugOwner, required Object super.debugOwner,
required GlobalKey customPaintKey, required GlobalKey customPaintKey,
required Duration pressDuration, required super.duration,
}) : _customPaintKey = customPaintKey, }) : _customPaintKey = customPaintKey;
super(
duration: pressDuration,
);
final GlobalKey _customPaintKey; final GlobalKey _customPaintKey;
...@@ -2105,10 +2131,9 @@ class _ThumbPressGestureRecognizer extends LongPressGestureRecognizer { ...@@ -2105,10 +2131,9 @@ class _ThumbPressGestureRecognizer extends LongPressGestureRecognizer {
// track and ignores everything else, including the thumb. // track and ignores everything else, including the thumb.
class _TrackTapGestureRecognizer extends TapGestureRecognizer { class _TrackTapGestureRecognizer extends TapGestureRecognizer {
_TrackTapGestureRecognizer({ _TrackTapGestureRecognizer({
required Object debugOwner, required super.debugOwner,
required GlobalKey customPaintKey, required GlobalKey customPaintKey,
}) : _customPaintKey = customPaintKey, }) : _customPaintKey = customPaintKey;
super(debugOwner: debugOwner);
final GlobalKey _customPaintKey; final GlobalKey _customPaintKey;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment