Few overscroll glow fixes. (#4610)

Fixes #4169 and also now overscroll indicator is dismissed the moment
user scrolls in the opposite direction (#4603) but the bounce overscroll
that happens behind the scene and is clamped in the indicator is still
problematic and needs to be fixed. However these fixes are orthogonal to that.

Also closes #4127 as I verified the timeout feature (reduced the duration
to 500ms to be closer to Android behaviour)
This commit is contained in:
Ali Ghassemi 2016-06-17 14:44:00 -07:00 committed by GitHub
parent d89823be2a
commit 94c4222f2b

View File

@ -13,7 +13,7 @@ const double _kMaxIndicatorExtent = 64.0;
const double _kMinIndicatorOpacity = 0.0; const double _kMinIndicatorOpacity = 0.0;
const double _kMaxIndicatorOpacity = 0.25; const double _kMaxIndicatorOpacity = 0.25;
const Duration _kIndicatorHideDuration = const Duration(milliseconds: 200); const Duration _kIndicatorHideDuration = const Duration(milliseconds: 200);
const Duration _kIndicatorTimeoutDuration = const Duration(seconds: 1); const Duration _kIndicatorTimeoutDuration = const Duration(milliseconds: 500);
final Tween<double> _kIndicatorOpacity = new Tween<double>(begin: 0.0, end: 0.3); final Tween<double> _kIndicatorOpacity = new Tween<double>(begin: 0.0, end: 0.3);
class _Painter extends CustomPainter { class _Painter extends CustomPainter {
@ -132,7 +132,10 @@ class _OverscrollIndicatorState extends State<OverscrollIndicator> {
void _hide() { void _hide() {
_hideTimer?.cancel(); _hideTimer?.cancel();
_hideTimer = null; _hideTimer = null;
_extentAnimation.reverse(); // Gaurding _hide() being called while indicator is already animating.
if (!_extentAnimation.isAnimating) {
_extentAnimation.reverse();
}
} }
void _updateState(ScrollableState scrollable) { void _updateState(ScrollableState scrollable) {
@ -151,12 +154,15 @@ class _OverscrollIndicatorState extends State<OverscrollIndicator> {
void _onScrollUpdated(ScrollableState scrollable) { void _onScrollUpdated(ScrollableState scrollable) {
final double value = scrollable.scrollOffset; final double value = scrollable.scrollOffset;
if ((value < _minScrollOffset || value > _maxScrollOffset) && if (_isOverscroll(value)) {
((value - _scrollOffset).abs() > kPixelScrollTolerance.distance)) { _refreshHideTimer();
_hideTimer?.cancel(); // Hide the indicator as soon as user starts scrolling in the reverse direction of overscroll.
_hideTimer = new Timer(_kIndicatorTimeoutDuration, _hide); if (_isReverseScroll(value)) {
// Changing the animation's value causes an implicit setState(). _hide();
_extentAnimation.value = value < _minScrollOffset ? _minScrollOffset - value : value - _maxScrollOffset; } else {
// Changing the animation's value causes an implicit setState().
_extentAnimation.value = value < _minScrollOffset ? _minScrollOffset - value : value - _maxScrollOffset;
}
} }
_updateState(scrollable); _updateState(scrollable);
} }
@ -166,6 +172,21 @@ class _OverscrollIndicatorState extends State<OverscrollIndicator> {
_hide(); _hide();
} }
void _refreshHideTimer() {
_hideTimer?.cancel();
_hideTimer = new Timer(_kIndicatorTimeoutDuration, _hide);
}
bool _isOverscroll(double scrollOffset) {
return (scrollOffset < _minScrollOffset || scrollOffset > _maxScrollOffset) &&
((scrollOffset - _scrollOffset).abs() > kPixelScrollTolerance.distance);
}
bool _isReverseScroll(double scrollOffset) {
final double delta = _scrollOffset - scrollOffset;
return scrollOffset < _minScrollOffset ? delta < 0 : delta > 0;
}
bool _handleScrollNotification(ScrollNotification notification) { bool _handleScrollNotification(ScrollNotification notification) {
if (config.scrollableKey == null || config.scrollableKey == notification.scrollable.config.key) { if (config.scrollableKey == null || config.scrollableKey == notification.scrollable.config.key) {
final ScrollableState scrollable = notification.scrollable; final ScrollableState scrollable = notification.scrollable;