Loading core/java/android/widget/AbsListView.java +176 −171 Original line number Diff line number Diff line Loading @@ -2771,15 +2771,21 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } } private boolean startScrollIfNeeded(int deltaY) { private boolean startScrollIfNeeded(int y) { // Check if we have moved far enough that it looks more like a // scroll than a tap final int deltaY = y - mMotionY; final int distance = Math.abs(deltaY); final boolean overscroll = mScrollY != 0; if (overscroll || distance > mTouchSlop) { createScrollingCache(); mTouchMode = overscroll ? TOUCH_MODE_OVERSCROLL : TOUCH_MODE_SCROLL; mMotionCorrection = deltaY; if (overscroll) { mTouchMode = TOUCH_MODE_OVERSCROLL; mMotionCorrection = 0; } else { mTouchMode = TOUCH_MODE_SCROLL; mMotionCorrection = deltaY > 0 ? mTouchSlop : -mTouchSlop; } final Handler handler = getHandler(); // Handler should not be null unless the AbsListView is not attached to a // window, which would make it very hard to scroll it... but the monkeys Loading @@ -2799,152 +2805,19 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te if (parent != null) { parent.requestDisallowInterceptTouchEvent(true); } scrollIfNeeded(y); return true; } return false; } public void onTouchModeChanged(boolean isInTouchMode) { if (isInTouchMode) { // Get rid of the selection when we enter touch mode hideSelector(); // Layout, but only if we already have done so previously. // (Otherwise may clobber a LAYOUT_SYNC layout that was requested to restore // state.) if (getHeight() > 0 && getChildCount() > 0) { // We do not lose focus initiating a touch (since AbsListView is focusable in // touch mode). Force an initial layout to get rid of the selection. layoutChildren(); } updateSelectorState(); } else { int touchMode = mTouchMode; if (touchMode == TOUCH_MODE_OVERSCROLL || touchMode == TOUCH_MODE_OVERFLING) { if (mFlingRunnable != null) { mFlingRunnable.endFling(); } if (mPositionScroller != null) { mPositionScroller.stop(); } if (mScrollY != 0) { mScrollY = 0; invalidateParentCaches(); finishGlows(); invalidate(); } } } } @Override public boolean onTouchEvent(MotionEvent ev) { if (!isEnabled()) { // A disabled view that is clickable still consumes the touch // events, it just doesn't respond to them. return isClickable() || isLongClickable(); } if (mFastScroller != null) { boolean intercepted = mFastScroller.onTouchEvent(ev); if (intercepted) { return true; } } final int action = ev.getAction(); View v; int deltaY; initVelocityTrackerIfNotExists(); mVelocityTracker.addMovement(ev); switch (action & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: { switch (mTouchMode) { case TOUCH_MODE_OVERFLING: { mFlingRunnable.endFling(); if (mPositionScroller != null) { mPositionScroller.stop(); } mTouchMode = TOUCH_MODE_OVERSCROLL; mMotionX = (int) ev.getX(); mMotionY = mLastY = (int) ev.getY(); mMotionCorrection = 0; mActivePointerId = ev.getPointerId(0); mDirection = 0; break; } default: { mActivePointerId = ev.getPointerId(0); final int x = (int) ev.getX(); final int y = (int) ev.getY(); int motionPosition = pointToPosition(x, y); if (!mDataChanged) { if ((mTouchMode != TOUCH_MODE_FLING) && (motionPosition >= 0) && (getAdapter().isEnabled(motionPosition))) { // User clicked on an actual view (and was not stopping a fling). // It might be a click or a scroll. Assume it is a click until // proven otherwise mTouchMode = TOUCH_MODE_DOWN; // FIXME Debounce if (mPendingCheckForTap == null) { mPendingCheckForTap = new CheckForTap(); } postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout()); } else { if (mTouchMode == TOUCH_MODE_FLING) { // Stopped a fling. It is a scroll. createScrollingCache(); mTouchMode = TOUCH_MODE_SCROLL; mMotionCorrection = 0; motionPosition = findMotionRow(y); mFlingRunnable.flywheelTouch(); } } } if (motionPosition >= 0) { // Remember where the motion event started v = getChildAt(motionPosition - mFirstPosition); mMotionViewOriginalTop = v.getTop(); } mMotionX = x; mMotionY = y; mMotionPosition = motionPosition; mLastY = Integer.MIN_VALUE; break; } } if (performButtonActionOnTouchDown(ev)) { if (mTouchMode == TOUCH_MODE_DOWN) { removeCallbacks(mPendingCheckForTap); } } break; } private void scrollIfNeeded(int y) { final int rawDeltaY = y - mMotionY; final int deltaY = rawDeltaY - mMotionCorrection; int incrementalDeltaY = mLastY != Integer.MIN_VALUE ? y - mLastY : deltaY; case MotionEvent.ACTION_MOVE: { int pointerIndex = ev.findPointerIndex(mActivePointerId); if (pointerIndex == -1) { pointerIndex = 0; mActivePointerId = ev.getPointerId(pointerIndex); } final int y = (int) ev.getY(pointerIndex); deltaY = y - mMotionY; switch (mTouchMode) { case TOUCH_MODE_DOWN: case TOUCH_MODE_TAP: case TOUCH_MODE_DONE_WAITING: // Check if we have moved far enough that it looks more like a // scroll than a tap startScrollIfNeeded(deltaY); break; case TOUCH_MODE_SCROLL: if (mTouchMode == TOUCH_MODE_SCROLL) { if (PROFILE_SCROLLING) { if (!mScrollProfilingStarted) { Debug.startMethodTracing("AbsListViewScroll"); Loading @@ -2962,17 +2835,13 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te // If so, we haven't disallowed intercepting touch events yet. // Make sure that we do so in case we're in a parent that can intercept. if ((mGroupFlags & FLAG_DISALLOW_INTERCEPT) == 0 && Math.abs(deltaY) > mTouchSlop) { Math.abs(rawDeltaY) > mTouchSlop) { final ViewParent parent = getParent(); if (parent != null) { parent.requestDisallowInterceptTouchEvent(true); } } final int rawDeltaY = deltaY; deltaY -= mMotionCorrection; int incrementalDeltaY = mLastY != Integer.MIN_VALUE ? y - mLastY : deltaY; final int motionIndex; if (mMotionPosition >= 0) { motionIndex = mMotionPosition - mFirstPosition; Loading Loading @@ -3038,14 +2907,8 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } mLastY = y; } break; case TOUCH_MODE_OVERSCROLL: } else if (mTouchMode == TOUCH_MODE_OVERSCROLL) { if (y != mLastY) { final int rawDeltaY = deltaY; deltaY -= mMotionCorrection; int incrementalDeltaY = mLastY != Integer.MIN_VALUE ? y - mLastY : deltaY; final int oldScroll = mScrollY; final int newScroll = oldScroll - incrementalDeltaY; int newDirection = y > mLastY ? 1 : -1; Loading Loading @@ -3109,9 +2972,151 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te mLastY = y; mDirection = newDirection; } } } public void onTouchModeChanged(boolean isInTouchMode) { if (isInTouchMode) { // Get rid of the selection when we enter touch mode hideSelector(); // Layout, but only if we already have done so previously. // (Otherwise may clobber a LAYOUT_SYNC layout that was requested to restore // state.) if (getHeight() > 0 && getChildCount() > 0) { // We do not lose focus initiating a touch (since AbsListView is focusable in // touch mode). Force an initial layout to get rid of the selection. layoutChildren(); } updateSelectorState(); } else { int touchMode = mTouchMode; if (touchMode == TOUCH_MODE_OVERSCROLL || touchMode == TOUCH_MODE_OVERFLING) { if (mFlingRunnable != null) { mFlingRunnable.endFling(); } if (mPositionScroller != null) { mPositionScroller.stop(); } if (mScrollY != 0) { mScrollY = 0; invalidateParentCaches(); finishGlows(); invalidate(); } } } } @Override public boolean onTouchEvent(MotionEvent ev) { if (!isEnabled()) { // A disabled view that is clickable still consumes the touch // events, it just doesn't respond to them. return isClickable() || isLongClickable(); } if (mFastScroller != null) { boolean intercepted = mFastScroller.onTouchEvent(ev); if (intercepted) { return true; } } final int action = ev.getAction(); View v; initVelocityTrackerIfNotExists(); mVelocityTracker.addMovement(ev); switch (action & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: { switch (mTouchMode) { case TOUCH_MODE_OVERFLING: { mFlingRunnable.endFling(); if (mPositionScroller != null) { mPositionScroller.stop(); } mTouchMode = TOUCH_MODE_OVERSCROLL; mMotionX = (int) ev.getX(); mMotionY = mLastY = (int) ev.getY(); mMotionCorrection = 0; mActivePointerId = ev.getPointerId(0); mDirection = 0; break; } default: { mActivePointerId = ev.getPointerId(0); final int x = (int) ev.getX(); final int y = (int) ev.getY(); int motionPosition = pointToPosition(x, y); if (!mDataChanged) { if ((mTouchMode != TOUCH_MODE_FLING) && (motionPosition >= 0) && (getAdapter().isEnabled(motionPosition))) { // User clicked on an actual view (and was not stopping a fling). // It might be a click or a scroll. Assume it is a click until // proven otherwise mTouchMode = TOUCH_MODE_DOWN; // FIXME Debounce if (mPendingCheckForTap == null) { mPendingCheckForTap = new CheckForTap(); } postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout()); } else { if (mTouchMode == TOUCH_MODE_FLING) { // Stopped a fling. It is a scroll. createScrollingCache(); mTouchMode = TOUCH_MODE_SCROLL; mMotionCorrection = 0; motionPosition = findMotionRow(y); mFlingRunnable.flywheelTouch(); } } } if (motionPosition >= 0) { // Remember where the motion event started v = getChildAt(motionPosition - mFirstPosition); mMotionViewOriginalTop = v.getTop(); } mMotionX = x; mMotionY = y; mMotionPosition = motionPosition; mLastY = Integer.MIN_VALUE; break; } } if (performButtonActionOnTouchDown(ev)) { if (mTouchMode == TOUCH_MODE_DOWN) { removeCallbacks(mPendingCheckForTap); } } break; } case MotionEvent.ACTION_MOVE: { int pointerIndex = ev.findPointerIndex(mActivePointerId); if (pointerIndex == -1) { pointerIndex = 0; mActivePointerId = ev.getPointerId(pointerIndex); } final int y = (int) ev.getY(pointerIndex); switch (mTouchMode) { case TOUCH_MODE_DOWN: case TOUCH_MODE_TAP: case TOUCH_MODE_DONE_WAITING: // Check if we have moved far enough that it looks more like a // scroll than a tap startScrollIfNeeded(y); break; case TOUCH_MODE_SCROLL: case TOUCH_MODE_OVERSCROLL: scrollIfNeeded(y); break; } break; } Loading Loading @@ -3542,7 +3547,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te final int y = (int) ev.getY(pointerIndex); initVelocityTrackerIfNotExists(); mVelocityTracker.addMovement(ev); if (startScrollIfNeeded(y - mMotionY)) { if (startScrollIfNeeded(y)) { return true; } break; Loading Loading
core/java/android/widget/AbsListView.java +176 −171 Original line number Diff line number Diff line Loading @@ -2771,15 +2771,21 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } } private boolean startScrollIfNeeded(int deltaY) { private boolean startScrollIfNeeded(int y) { // Check if we have moved far enough that it looks more like a // scroll than a tap final int deltaY = y - mMotionY; final int distance = Math.abs(deltaY); final boolean overscroll = mScrollY != 0; if (overscroll || distance > mTouchSlop) { createScrollingCache(); mTouchMode = overscroll ? TOUCH_MODE_OVERSCROLL : TOUCH_MODE_SCROLL; mMotionCorrection = deltaY; if (overscroll) { mTouchMode = TOUCH_MODE_OVERSCROLL; mMotionCorrection = 0; } else { mTouchMode = TOUCH_MODE_SCROLL; mMotionCorrection = deltaY > 0 ? mTouchSlop : -mTouchSlop; } final Handler handler = getHandler(); // Handler should not be null unless the AbsListView is not attached to a // window, which would make it very hard to scroll it... but the monkeys Loading @@ -2799,152 +2805,19 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te if (parent != null) { parent.requestDisallowInterceptTouchEvent(true); } scrollIfNeeded(y); return true; } return false; } public void onTouchModeChanged(boolean isInTouchMode) { if (isInTouchMode) { // Get rid of the selection when we enter touch mode hideSelector(); // Layout, but only if we already have done so previously. // (Otherwise may clobber a LAYOUT_SYNC layout that was requested to restore // state.) if (getHeight() > 0 && getChildCount() > 0) { // We do not lose focus initiating a touch (since AbsListView is focusable in // touch mode). Force an initial layout to get rid of the selection. layoutChildren(); } updateSelectorState(); } else { int touchMode = mTouchMode; if (touchMode == TOUCH_MODE_OVERSCROLL || touchMode == TOUCH_MODE_OVERFLING) { if (mFlingRunnable != null) { mFlingRunnable.endFling(); } if (mPositionScroller != null) { mPositionScroller.stop(); } if (mScrollY != 0) { mScrollY = 0; invalidateParentCaches(); finishGlows(); invalidate(); } } } } @Override public boolean onTouchEvent(MotionEvent ev) { if (!isEnabled()) { // A disabled view that is clickable still consumes the touch // events, it just doesn't respond to them. return isClickable() || isLongClickable(); } if (mFastScroller != null) { boolean intercepted = mFastScroller.onTouchEvent(ev); if (intercepted) { return true; } } final int action = ev.getAction(); View v; int deltaY; initVelocityTrackerIfNotExists(); mVelocityTracker.addMovement(ev); switch (action & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: { switch (mTouchMode) { case TOUCH_MODE_OVERFLING: { mFlingRunnable.endFling(); if (mPositionScroller != null) { mPositionScroller.stop(); } mTouchMode = TOUCH_MODE_OVERSCROLL; mMotionX = (int) ev.getX(); mMotionY = mLastY = (int) ev.getY(); mMotionCorrection = 0; mActivePointerId = ev.getPointerId(0); mDirection = 0; break; } default: { mActivePointerId = ev.getPointerId(0); final int x = (int) ev.getX(); final int y = (int) ev.getY(); int motionPosition = pointToPosition(x, y); if (!mDataChanged) { if ((mTouchMode != TOUCH_MODE_FLING) && (motionPosition >= 0) && (getAdapter().isEnabled(motionPosition))) { // User clicked on an actual view (and was not stopping a fling). // It might be a click or a scroll. Assume it is a click until // proven otherwise mTouchMode = TOUCH_MODE_DOWN; // FIXME Debounce if (mPendingCheckForTap == null) { mPendingCheckForTap = new CheckForTap(); } postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout()); } else { if (mTouchMode == TOUCH_MODE_FLING) { // Stopped a fling. It is a scroll. createScrollingCache(); mTouchMode = TOUCH_MODE_SCROLL; mMotionCorrection = 0; motionPosition = findMotionRow(y); mFlingRunnable.flywheelTouch(); } } } if (motionPosition >= 0) { // Remember where the motion event started v = getChildAt(motionPosition - mFirstPosition); mMotionViewOriginalTop = v.getTop(); } mMotionX = x; mMotionY = y; mMotionPosition = motionPosition; mLastY = Integer.MIN_VALUE; break; } } if (performButtonActionOnTouchDown(ev)) { if (mTouchMode == TOUCH_MODE_DOWN) { removeCallbacks(mPendingCheckForTap); } } break; } private void scrollIfNeeded(int y) { final int rawDeltaY = y - mMotionY; final int deltaY = rawDeltaY - mMotionCorrection; int incrementalDeltaY = mLastY != Integer.MIN_VALUE ? y - mLastY : deltaY; case MotionEvent.ACTION_MOVE: { int pointerIndex = ev.findPointerIndex(mActivePointerId); if (pointerIndex == -1) { pointerIndex = 0; mActivePointerId = ev.getPointerId(pointerIndex); } final int y = (int) ev.getY(pointerIndex); deltaY = y - mMotionY; switch (mTouchMode) { case TOUCH_MODE_DOWN: case TOUCH_MODE_TAP: case TOUCH_MODE_DONE_WAITING: // Check if we have moved far enough that it looks more like a // scroll than a tap startScrollIfNeeded(deltaY); break; case TOUCH_MODE_SCROLL: if (mTouchMode == TOUCH_MODE_SCROLL) { if (PROFILE_SCROLLING) { if (!mScrollProfilingStarted) { Debug.startMethodTracing("AbsListViewScroll"); Loading @@ -2962,17 +2835,13 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te // If so, we haven't disallowed intercepting touch events yet. // Make sure that we do so in case we're in a parent that can intercept. if ((mGroupFlags & FLAG_DISALLOW_INTERCEPT) == 0 && Math.abs(deltaY) > mTouchSlop) { Math.abs(rawDeltaY) > mTouchSlop) { final ViewParent parent = getParent(); if (parent != null) { parent.requestDisallowInterceptTouchEvent(true); } } final int rawDeltaY = deltaY; deltaY -= mMotionCorrection; int incrementalDeltaY = mLastY != Integer.MIN_VALUE ? y - mLastY : deltaY; final int motionIndex; if (mMotionPosition >= 0) { motionIndex = mMotionPosition - mFirstPosition; Loading Loading @@ -3038,14 +2907,8 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } mLastY = y; } break; case TOUCH_MODE_OVERSCROLL: } else if (mTouchMode == TOUCH_MODE_OVERSCROLL) { if (y != mLastY) { final int rawDeltaY = deltaY; deltaY -= mMotionCorrection; int incrementalDeltaY = mLastY != Integer.MIN_VALUE ? y - mLastY : deltaY; final int oldScroll = mScrollY; final int newScroll = oldScroll - incrementalDeltaY; int newDirection = y > mLastY ? 1 : -1; Loading Loading @@ -3109,9 +2972,151 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te mLastY = y; mDirection = newDirection; } } } public void onTouchModeChanged(boolean isInTouchMode) { if (isInTouchMode) { // Get rid of the selection when we enter touch mode hideSelector(); // Layout, but only if we already have done so previously. // (Otherwise may clobber a LAYOUT_SYNC layout that was requested to restore // state.) if (getHeight() > 0 && getChildCount() > 0) { // We do not lose focus initiating a touch (since AbsListView is focusable in // touch mode). Force an initial layout to get rid of the selection. layoutChildren(); } updateSelectorState(); } else { int touchMode = mTouchMode; if (touchMode == TOUCH_MODE_OVERSCROLL || touchMode == TOUCH_MODE_OVERFLING) { if (mFlingRunnable != null) { mFlingRunnable.endFling(); } if (mPositionScroller != null) { mPositionScroller.stop(); } if (mScrollY != 0) { mScrollY = 0; invalidateParentCaches(); finishGlows(); invalidate(); } } } } @Override public boolean onTouchEvent(MotionEvent ev) { if (!isEnabled()) { // A disabled view that is clickable still consumes the touch // events, it just doesn't respond to them. return isClickable() || isLongClickable(); } if (mFastScroller != null) { boolean intercepted = mFastScroller.onTouchEvent(ev); if (intercepted) { return true; } } final int action = ev.getAction(); View v; initVelocityTrackerIfNotExists(); mVelocityTracker.addMovement(ev); switch (action & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: { switch (mTouchMode) { case TOUCH_MODE_OVERFLING: { mFlingRunnable.endFling(); if (mPositionScroller != null) { mPositionScroller.stop(); } mTouchMode = TOUCH_MODE_OVERSCROLL; mMotionX = (int) ev.getX(); mMotionY = mLastY = (int) ev.getY(); mMotionCorrection = 0; mActivePointerId = ev.getPointerId(0); mDirection = 0; break; } default: { mActivePointerId = ev.getPointerId(0); final int x = (int) ev.getX(); final int y = (int) ev.getY(); int motionPosition = pointToPosition(x, y); if (!mDataChanged) { if ((mTouchMode != TOUCH_MODE_FLING) && (motionPosition >= 0) && (getAdapter().isEnabled(motionPosition))) { // User clicked on an actual view (and was not stopping a fling). // It might be a click or a scroll. Assume it is a click until // proven otherwise mTouchMode = TOUCH_MODE_DOWN; // FIXME Debounce if (mPendingCheckForTap == null) { mPendingCheckForTap = new CheckForTap(); } postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout()); } else { if (mTouchMode == TOUCH_MODE_FLING) { // Stopped a fling. It is a scroll. createScrollingCache(); mTouchMode = TOUCH_MODE_SCROLL; mMotionCorrection = 0; motionPosition = findMotionRow(y); mFlingRunnable.flywheelTouch(); } } } if (motionPosition >= 0) { // Remember where the motion event started v = getChildAt(motionPosition - mFirstPosition); mMotionViewOriginalTop = v.getTop(); } mMotionX = x; mMotionY = y; mMotionPosition = motionPosition; mLastY = Integer.MIN_VALUE; break; } } if (performButtonActionOnTouchDown(ev)) { if (mTouchMode == TOUCH_MODE_DOWN) { removeCallbacks(mPendingCheckForTap); } } break; } case MotionEvent.ACTION_MOVE: { int pointerIndex = ev.findPointerIndex(mActivePointerId); if (pointerIndex == -1) { pointerIndex = 0; mActivePointerId = ev.getPointerId(pointerIndex); } final int y = (int) ev.getY(pointerIndex); switch (mTouchMode) { case TOUCH_MODE_DOWN: case TOUCH_MODE_TAP: case TOUCH_MODE_DONE_WAITING: // Check if we have moved far enough that it looks more like a // scroll than a tap startScrollIfNeeded(y); break; case TOUCH_MODE_SCROLL: case TOUCH_MODE_OVERSCROLL: scrollIfNeeded(y); break; } break; } Loading Loading @@ -3542,7 +3547,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te final int y = (int) ev.getY(pointerIndex); initVelocityTrackerIfNotExists(); mVelocityTracker.addMovement(ev); if (startScrollIfNeeded(y - mMotionY)) { if (startScrollIfNeeded(y)) { return true; } break; Loading