Skip to content

Commit 23713eb

Browse files
author
Chris Banes
committed
Fix Bug that can be caused by the user pressing on a View while we're overscrolling
1 parent 5781477 commit 23713eb

File tree

2 files changed

+107
-79
lines changed

2 files changed

+107
-79
lines changed

library/src/com/handmark/pulltorefresh/library/OverscrollHelper.java

Lines changed: 69 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import android.view.View;
2121

2222
import com.handmark.pulltorefresh.library.PullToRefreshBase.Mode;
23+
import com.handmark.pulltorefresh.library.PullToRefreshBase.State;
2324

2425
@TargetApi(9)
2526
public final class OverscrollHelper {
@@ -34,18 +35,18 @@ public final class OverscrollHelper {
3435
* This should only be used on AdapterView's such as ListView as it just
3536
* calls through to overScrollBy() with the scrollRange = 0. AdapterView's
3637
* do not have a scroll range (i.e. getScrollY() doesn't work).
37-
*
38-
* @param view - PullToRefreshView that is calling this.
39-
* @param deltaX - Change in X in pixels, passed through from from overScrollBy
40-
* call
41-
* @param scrollX - Current X scroll value in pixels before applying deltaY,
42-
* passed through from from overScrollBy call
43-
* @param deltaY - Change in Y in pixels, passed through from from overScrollBy
44-
* call
45-
* @param scrollY - Current Y scroll value in pixels before applying deltaY,
46-
* passed through from from overScrollBy call
47-
* @param isTouchEvent - true if this scroll operation is the result of a touch
48-
* event, passed through from from overScrollBy call
38+
*
39+
* @param view - PullToRefreshView that is calling this.
40+
* @param deltaX - Change in X in pixels, passed through from from
41+
* overScrollBy call
42+
* @param scrollX - Current X scroll value in pixels before applying deltaY,
43+
* passed through from from overScrollBy call
44+
* @param deltaY - Change in Y in pixels, passed through from from
45+
* overScrollBy call
46+
* @param scrollY - Current Y scroll value in pixels before applying deltaY,
47+
* passed through from from overScrollBy call
48+
* @param isTouchEvent - true if this scroll operation is the result of a
49+
* touch event, passed through from from overScrollBy call
4950
*/
5051
public static void overScrollBy(final PullToRefreshBase<?> view, final int deltaX, final int scrollX,
5152
final int deltaY, final int scrollY, final boolean isTouchEvent) {
@@ -56,19 +57,20 @@ public static void overScrollBy(final PullToRefreshBase<?> view, final int delta
5657
* Helper method for Overscrolling that encapsulates all of the necessary
5758
* function. This version of the call is used for Views that need to specify
5859
* a Scroll Range but scroll back to it's edge correctly.
59-
*
60-
* @param view - PullToRefreshView that is calling this.
61-
* @param deltaX - Change in X in pixels, passed through from from overScrollBy
62-
* call
63-
* @param scrollX - Current X scroll value in pixels before applying deltaY,
64-
* passed through from from overScrollBy call
65-
* @param deltaY - Change in Y in pixels, passed through from from overScrollBy
66-
* call
67-
* @param scrollY - Current Y scroll value in pixels before applying deltaY,
68-
* passed through from from overScrollBy call
69-
* @param scrollRange - Scroll Range of the View, specifically needed for ScrollView
70-
* @param isTouchEvent - true if this scroll operation is the result of a touch
71-
* event, passed through from from overScrollBy call
60+
*
61+
* @param view - PullToRefreshView that is calling this.
62+
* @param deltaX - Change in X in pixels, passed through from from
63+
* overScrollBy call
64+
* @param scrollX - Current X scroll value in pixels before applying deltaY,
65+
* passed through from from overScrollBy call
66+
* @param deltaY - Change in Y in pixels, passed through from from
67+
* overScrollBy call
68+
* @param scrollY - Current Y scroll value in pixels before applying deltaY,
69+
* passed through from from overScrollBy call
70+
* @param scrollRange - Scroll Range of the View, specifically needed for
71+
* ScrollView
72+
* @param isTouchEvent - true if this scroll operation is the result of a
73+
* touch event, passed through from from overScrollBy call
7274
*/
7375
public static void overScrollBy(final PullToRefreshBase<?> view, final int deltaX, final int scrollX,
7476
final int deltaY, final int scrollY, final int scrollRange, final boolean isTouchEvent) {
@@ -78,23 +80,24 @@ public static void overScrollBy(final PullToRefreshBase<?> view, final int delta
7880
/**
7981
* Helper method for Overscrolling that encapsulates all of the necessary
8082
* function. This is the advanced version of the call.
81-
*
82-
* @param view - PullToRefreshView that is calling this.
83-
* @param deltaX - Change in X in pixels, passed through from from overScrollBy
84-
* call
85-
* @param scrollX - Current X scroll value in pixels before applying deltaY,
86-
* passed through from from overScrollBy call
87-
* @param deltaY - Change in Y in pixels, passed through from from overScrollBy
88-
* call
89-
* @param scrollY - Current Y scroll value in pixels before applying deltaY,
90-
* passed through from from overScrollBy call
91-
* @param scrollRange - Scroll Range of the View, specifically needed for ScrollView
92-
* @param fuzzyThreshold - Threshold for which the values how fuzzy we should treat the
93-
* other values. Needed for WebView as it doesn't always scroll
94-
* back to it's edge. 0 = no fuzziness.
95-
* @param scaleFactor - Scale Factor for overscroll amount
96-
* @param isTouchEvent - true if this scroll operation is the result of a touch
97-
* event, passed through from from overScrollBy call
83+
*
84+
* @param view - PullToRefreshView that is calling this.
85+
* @param deltaX - Change in X in pixels, passed through from from
86+
* overScrollBy call
87+
* @param scrollX - Current X scroll value in pixels before applying deltaY,
88+
* passed through from from overScrollBy call
89+
* @param deltaY - Change in Y in pixels, passed through from from
90+
* overScrollBy call
91+
* @param scrollY - Current Y scroll value in pixels before applying deltaY,
92+
* passed through from from overScrollBy call
93+
* @param scrollRange - Scroll Range of the View, specifically needed for
94+
* ScrollView
95+
* @param fuzzyThreshold - Threshold for which the values how fuzzy we
96+
* should treat the other values. Needed for WebView as it
97+
* doesn't always scroll back to it's edge. 0 = no fuzziness.
98+
* @param scaleFactor - Scale Factor for overscroll amount
99+
* @param isTouchEvent - true if this scroll operation is the result of a
100+
* touch event, passed through from from overScrollBy call
98101
*/
99102
public static void overScrollBy(final PullToRefreshBase<?> view, final int deltaX, final int scrollX,
100103
final int deltaY, final int scrollY, final int scrollRange, final int fuzzyThreshold,
@@ -125,29 +128,45 @@ public static void overScrollBy(final PullToRefreshBase<?> view, final int delta
125128
final int newScrollValue = (deltaValue + scrollValue);
126129

127130
if (PullToRefreshBase.DEBUG) {
128-
Log.d(LOG_TAG, "OverScroll. DeltaX: " + deltaX + ", ScrollX: " + scrollX + ", DeltaY: " + deltaY +
129-
", ScrollY: " + scrollY + ", NewY: " + newScrollValue + ", ScrollRange: " + scrollRange +
130-
", CurrentScroll: " + currentScrollValue);
131+
Log.d(LOG_TAG, "OverScroll. DeltaX: " + deltaX + ", ScrollX: " + scrollX + ", DeltaY: " + deltaY
132+
+ ", ScrollY: " + scrollY + ", NewY: " + newScrollValue + ", ScrollRange: " + scrollRange
133+
+ ", CurrentScroll: " + currentScrollValue);
131134
}
132135

133136
if (newScrollValue < (0 - fuzzyThreshold)) {
134137
// Check the mode supports the overscroll direction, and
135138
// then move scroll
136139
if (mode.showHeaderLoadingLayout()) {
140+
// If we're currently at zero, we're about to start
141+
// overscrolling, so change the state
142+
if (currentScrollValue == 0) {
143+
view.setState(State.OVERSCROLLING);
144+
}
145+
137146
view.setHeaderScroll((int) (scaleFactor * (currentScrollValue + newScrollValue)));
138147
}
139148
} else if (newScrollValue > (scrollRange + fuzzyThreshold)) {
140149
// Check the mode supports the overscroll direction, and
141150
// then move scroll
142151
if (mode.showFooterLoadingLayout()) {
143-
view.setHeaderScroll((int) (scaleFactor * (currentScrollValue + newScrollValue -
144-
scrollRange)));
152+
// If we're currently at zero, we're about to start
153+
// overscrolling, so change the state
154+
if (currentScrollValue == 0) {
155+
view.setState(State.OVERSCROLLING);
156+
}
157+
158+
view.setHeaderScroll((int) (scaleFactor * (currentScrollValue + newScrollValue - scrollRange)));
145159
}
146-
} else if (Math.abs(newScrollValue) <= fuzzyThreshold || Math.abs(newScrollValue - scrollRange) <=
147-
fuzzyThreshold) {
160+
} else if (Math.abs(newScrollValue) <= fuzzyThreshold
161+
|| Math.abs(newScrollValue - scrollRange) <= fuzzyThreshold) {
148162
// Means we've stopped overscrolling, so scroll back to 0
149-
view.smoothScrollToLonger(0);
163+
view.setState(State.RESET);
150164
}
165+
} else if (isTouchEvent && State.OVERSCROLLING == view.getState()) {
166+
// This condition means that we were overscrolling from a fling,
167+
// but the user has touched the View and is now overscrolling
168+
// from touch instead. We need to just reset.
169+
view.setState(State.RESET);
151170
}
152171
}
153172
}

library/src/com/handmark/pulltorefresh/library/PullToRefreshBase.java

Lines changed: 38 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,37 @@ void onReset() {
615615
resetHeader();
616616
}
617617

618+
final void setState(State state, final boolean... params) {
619+
mState = state;
620+
if (DEBUG) {
621+
Log.d(LOG_TAG, "State: " + mState.name());
622+
}
623+
624+
switch (mState) {
625+
case RESET:
626+
onReset();
627+
break;
628+
case PULL_TO_REFRESH:
629+
onPullToRefresh();
630+
break;
631+
case RELEASE_TO_REFRESH:
632+
onReleaseToRefresh();
633+
break;
634+
case REFRESHING:
635+
case MANUAL_REFRESHING:
636+
onRefreshing(params[0]);
637+
break;
638+
case OVERSCROLLING:
639+
// NO-OP
640+
break;
641+
}
642+
643+
// Call OnPullEventListener
644+
if (null != mOnPullEventListener) {
645+
mOnPullEventListener.onPullEvent(this, mState, mCurrentMode);
646+
}
647+
}
648+
618649
/**
619650
* Used internally for adding view. Need because we override addView to
620651
* pass-through to the Refreshable View
@@ -1130,34 +1161,6 @@ private void refreshLoadingViewsSize() {
11301161
setPadding(pLeft, pTop, pRight, pBottom);
11311162
}
11321163

1133-
private void setState(State state, final boolean... params) {
1134-
mState = state;
1135-
if (DEBUG) {
1136-
Log.d(LOG_TAG, "State: " + mState.name());
1137-
}
1138-
1139-
switch (mState) {
1140-
case RESET:
1141-
onReset();
1142-
break;
1143-
case PULL_TO_REFRESH:
1144-
onPullToRefresh();
1145-
break;
1146-
case RELEASE_TO_REFRESH:
1147-
onReleaseToRefresh();
1148-
break;
1149-
case REFRESHING:
1150-
case MANUAL_REFRESHING:
1151-
onRefreshing(params[0]);
1152-
break;
1153-
}
1154-
1155-
// Call OnPullEventListener
1156-
if (null != mOnPullEventListener) {
1157-
mOnPullEventListener.onPullEvent(this, mState, mCurrentMode);
1158-
}
1159-
}
1160-
11611164
/**
11621165
* Smooth Scroll to position using the specific duration
11631166
*
@@ -1470,7 +1473,13 @@ public static enum State {
14701473
* When the UI is currently refreshing, caused by a call to
14711474
* {@link PullToRefreshBase#setRefreshing() setRefreshing()}.
14721475
*/
1473-
MANUAL_REFRESHING(0x9);
1476+
MANUAL_REFRESHING(0x9),
1477+
1478+
/**
1479+
* When the UI is currently overscrolling, caused by a fling on the
1480+
* Refreshable View.
1481+
*/
1482+
OVERSCROLLING(0x10);
14741483

14751484
/**
14761485
* Maps an int to a specific state. This is needed when saving state.

0 commit comments

Comments
 (0)