Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4cd47702 authored by Adam Powell's avatar Adam Powell
Browse files

HorizontalScrollView multitouch scroll and only grip on content

AbsListView multitouch scroll and only grip on content
parent 5be65ab5
Loading
Loading
Loading
Loading
+100 −17
Original line number Diff line number Diff line
@@ -468,6 +468,18 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
    // dispatchDisplayHint()
    private boolean mPopupHidden;
    
    /**
     * ID of the active pointer. This is used to retain consistency during
     * drags/flings if multiple pointers are used.
     */
    private int mActivePointerId = INVALID_POINTER;
    
    /**
     * Sentinel value for no current active pointer.
     * Used by {@link #mActivePointerId}.
     */
    private static final int INVALID_POINTER = -1;

    /**
     * Interface definition for a callback to be invoked when the list or grid
     * has been scrolled.
@@ -1995,8 +2007,6 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
        }

        final int action = ev.getAction();
        final int x = (int) ev.getX();
        final int y = (int) ev.getY();

        View v;
        int deltaY;
@@ -2006,18 +2016,22 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
        }
        mVelocityTracker.addMovement(ev);

        switch (action) {
        switch (action & MotionEvent.ACTION_MASK) {
        case MotionEvent.ACTION_DOWN: {
            switch (mTouchMode) {
            case TOUCH_MODE_OVERFLING: {
                mFlingRunnable.endFling();
                mTouchMode = TOUCH_MODE_OVERSCROLL;
                mLastY = y;
                mLastY = (int) ev.getY();
                mMotionCorrection = 0;
                mActivePointerId = ev.getPointerId(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)
@@ -2037,7 +2051,9 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
                            // code in ViewRoot to try to find a nearby view to select
                            return false;
                        }
                        // User clicked on whitespace, or stopped a fling. It is a scroll.
                        
                        if (mTouchMode == TOUCH_MODE_FLING) {
                            // Stopped a fling. It is a scroll.
                            createScrollingCache();
                            mTouchMode = TOUCH_MODE_SCROLL;
                            mMotionCorrection = 0;
@@ -2045,6 +2061,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
                            reportScrollStateChange(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL);
                        }
                    }
                }

                if (motionPosition >= 0) {
                    // Remember where the motion event started
@@ -2062,6 +2079,8 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
        }

        case MotionEvent.ACTION_MOVE: {
            final int pointerIndex = ev.findPointerIndex(mActivePointerId);
            final int y = (int) ev.getY(pointerIndex);
            deltaY = y - mMotionY;
            switch (mTouchMode) {
            case TOUCH_MODE_DOWN:
@@ -2142,7 +2161,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te

                            // We did not scroll the full amount. Treat this essentially like the
                            // start of a new touch scroll
                            final int motionPosition = findMotionRow(y);
                            final int motionPosition = findClosestMotionRow(y);

                            mMotionCorrection = 0;
                            motionView = getChildAt(motionPosition - mFirstPosition);
@@ -2238,7 +2257,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
                    } else {
                        final VelocityTracker velocityTracker = mVelocityTracker;
                        velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
                        final int initialVelocity = (int) velocityTracker.getYVelocity();
                        final int initialVelocity = (int) velocityTracker.getYVelocity(mActivePointerId);
    
                        if (Math.abs(initialVelocity) > mMinimumVelocity) {
                            if (mFlingRunnable == null) {
@@ -2264,7 +2283,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
                }
                final VelocityTracker velocityTracker = mVelocityTracker;
                velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
                final int initialVelocity = (int) velocityTracker.getYVelocity();
                final int initialVelocity = (int) velocityTracker.getYVelocity(mActivePointerId);

                reportScrollStateChange(OnScrollListener.SCROLL_STATE_FLING);
                if (Math.abs(initialVelocity) > mMinimumVelocity) {
@@ -2291,6 +2310,8 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
                mVelocityTracker = null;
            }
            
            mActivePointerId = INVALID_POINTER;

            if (PROFILE_SCROLLING) {
                if (mScrollProfilingStarted) {
                    Debug.stopMethodTracing();
@@ -2332,6 +2353,24 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
                    mVelocityTracker = null;
                }
            }
            
            mActivePointerId = INVALID_POINTER;
            break;
        }
        
        case MotionEvent.ACTION_POINTER_UP: {
            onSecondaryPointerUp(ev);
            final int x = mMotionX;
            final int y = mMotionY;
            final int motionPosition = pointToPosition(x, y);
            if (motionPosition >= 0) {
                // Remember where the motion event started
                v = getChildAt(motionPosition - mFirstPosition);
                mMotionViewOriginalTop = v.getTop();
                mMotionPosition = motionPosition;
            }
            mLastY = y;
            break;
        }
        }

@@ -2380,8 +2419,6 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        int action = ev.getAction();
        int x = (int) ev.getX();
        int y = (int) ev.getY();
        View v;

        if (mFastScroller != null) {
@@ -2391,13 +2428,17 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
            }
        }

        switch (action) {
        switch (action & MotionEvent.ACTION_MASK) {
        case MotionEvent.ACTION_DOWN: {
            int touchMode = mTouchMode;
            if (touchMode == TOUCH_MODE_OVERFLING || touchMode == TOUCH_MODE_OVERSCROLL) {
                return true;
            }
            
            final int x = (int) ev.getX();
            final int y = (int) ev.getY();
            mActivePointerId = ev.getPointerId(0);
            
            int motionPosition = findMotionRow(y);
            if (touchMode != TOUCH_MODE_FLING && motionPosition >= 0) {
                // User clicked on an actual view (and was not stopping a fling).
@@ -2420,6 +2461,8 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
        case MotionEvent.ACTION_MOVE: {
            switch (mTouchMode) {
            case TOUCH_MODE_DOWN:
                final int pointerIndex = ev.findPointerIndex(mActivePointerId);
                final int y = (int) ev.getY(pointerIndex);
                if (startScrollIfNeeded(y - mMotionY)) {
                    return true;
                }
@@ -2430,14 +2473,38 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te

        case MotionEvent.ACTION_UP: {
            mTouchMode = TOUCH_MODE_REST;
            mActivePointerId = INVALID_POINTER;
            reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
            break;
        }
        
        case MotionEvent.ACTION_POINTER_UP: {
            onSecondaryPointerUp(ev);
            break;
        }
        }

        return false;
    }
    
    private void onSecondaryPointerUp(MotionEvent ev) {
        final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >>
                MotionEvent.ACTION_POINTER_INDEX_SHIFT;
        final int pointerId = ev.getPointerId(pointerIndex);
        if (pointerId == mActivePointerId) {
            // This was our active pointer going up. Choose a new
            // active pointer and adjust accordingly.
            // TODO: Make this decision more intelligent.
            final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
            mMotionX = (int) ev.getX(newPointerIndex);
            mMotionY = (int) ev.getY(newPointerIndex);
            mActivePointerId = ev.getPointerId(newPointerIndex);
            if (mVelocityTracker != null) {
                mVelocityTracker.clear();
            }
        }
    }

    /**
     * {@inheritDoc}
     */
@@ -3150,10 +3217,26 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
     * Find the row closest to y. This row will be used as the motion row when scrolling
     *
     * @param y Where the user touched
     * @return The position of the first (or only) item in the row closest to y
     * @return The position of the first (or only) item in the row containing y
     */
    abstract int findMotionRow(int y);
    
    /**
     * Find the row closest to y. This row will be used as the motion row when scrolling.
     * 
     * @param y Where the user touched
     * @return The position of the first (or only) item in the row closest to y
     */
    int findClosestMotionRow(int y) {
        final int childCount = getChildCount();
        if (childCount == 0) {
            return INVALID_POSITION;
        }
        
        final int motionRow = findMotionRow(y);
        return motionRow != INVALID_POSITION ? motionRow : mFirstPosition + childCount - 1;
    }

    /**
     * Causes all the views to be rebuilt and redrawn.
     */
+0 −2
Original line number Diff line number Diff line
@@ -431,8 +431,6 @@ public class GridView extends AbsListView {
                    }
                }
            }

            return mFirstPosition + childCount - 1;
        }
        return INVALID_POSITION;
    }
+106 −31
Original line number Diff line number Diff line
@@ -117,6 +117,18 @@ public class HorizontalScrollView extends FrameLayout {
    private int mMinimumVelocity;
    private int mMaximumVelocity;
    
    /**
     * ID of the active pointer. This is used to retain consistency during
     * drags/flings if multiple pointers are used.
     */
    private int mActivePointerId = INVALID_POINTER;
    
    /**
     * Sentinel value for no current active pointer.
     * Used by {@link #mActivePointerId}.
     */
    private static final int INVALID_POINTER = -1;
    
    public HorizontalScrollView(Context context) {
        this(context, null);
    }
@@ -362,6 +374,17 @@ public class HorizontalScrollView extends FrameLayout {
        return handled;
    }

    private boolean inChild(int x, int y) {
        if (getChildCount() > 0) {
            final View child = getChildAt(0);
            return !(y < child.getTop()
                    || y >= child.getBottom()
                    || x < child.getLeft()
                    || x >= child.getRight());
        }
        return false;
    }
    
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        /*
@@ -380,10 +403,8 @@ public class HorizontalScrollView extends FrameLayout {
            return true;
        }

        final float x = ev.getX();

        switch (action) {
            case MotionEvent.ACTION_MOVE:
        switch (action & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_MOVE: {
                /*
                 * mIsBeingDragged == false, otherwise the shortcut would have caught it. Check
                 * whether the user has moved far enough from his original down touch.
@@ -393,16 +414,30 @@ public class HorizontalScrollView extends FrameLayout {
                * Locally do absolute value. mLastMotionX is set to the x value
                * of the down event.
                */
                final int pointerIndex = ev.findPointerIndex(mActivePointerId);
                final float x = ev.getX(pointerIndex);
                final int xDiff = (int) Math.abs(x - mLastMotionX);
                if (xDiff > mTouchSlop) {
                    mIsBeingDragged = true;
                    mLastMotionX = x;
                    if (mParent != null) mParent.requestDisallowInterceptTouchEvent(true);
                }
                break;
            }

            case MotionEvent.ACTION_DOWN: {
                final float x = ev.getX();
                if (!inChild((int) x, (int) ev.getY())) {
                    mIsBeingDragged = false;
                    break;
                }
                
            case MotionEvent.ACTION_DOWN:
                /* Remember location of down touch */
                /*
                 * Remember location of down touch.
                 * ACTION_DOWN always refers to pointer index 0.
                 */
                mLastMotionX = x;
                mActivePointerId = ev.getPointerId(0);

                /*
                * If being flinged and user touches the screen, initiate drag;
@@ -411,11 +446,16 @@ public class HorizontalScrollView extends FrameLayout {
                */
                mIsBeingDragged = !mScroller.isFinished();
                break;
            }

            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                /* Release the drag */
                mIsBeingDragged = false;
                mActivePointerId = INVALID_POINTER;
                break;
            case MotionEvent.ACTION_POINTER_UP:
                onSecondaryPointerUp(ev);
                break;
        }

@@ -441,10 +481,9 @@ public class HorizontalScrollView extends FrameLayout {
        mVelocityTracker.addMovement(ev);

        final int action = ev.getAction();
        final float x = ev.getX();

        switch (action) {
            case MotionEvent.ACTION_DOWN:
        switch (action & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN: {
                /*
                * If being flinged and user touches, stop the fling. isFinished
                * will be false if being flinged.
@@ -453,21 +492,32 @@ public class HorizontalScrollView extends FrameLayout {
                    mScroller.abortAnimation();
                }
                
                final float x = ev.getX();
                if (!(mIsBeingDragged = inChild((int) x, (int) ev.getY()))) {
                    return false;
                }

                // Remember where the motion event started
                mLastMotionX = x;
                break;
            }
            case MotionEvent.ACTION_MOVE:
                if (mIsBeingDragged) {
                    // Scroll to follow the motion event
                    final int activePointerIndex = ev.findPointerIndex(mActivePointerId);
                    final float x = ev.getX(activePointerIndex);
                    final int deltaX = (int) (mLastMotionX - x);
                    mLastMotionX = x;

                    overscrollBy(deltaX, 0, mScrollX, 0, getScrollRange(), 0,
                            getOverscrollMax(), 0);
                }
                break;
            case MotionEvent.ACTION_UP:
                if (mIsBeingDragged) {
                    final VelocityTracker velocityTracker = mVelocityTracker;
                    velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
                int initialVelocity = (int) velocityTracker.getXVelocity();
                    int initialVelocity = (int) velocityTracker.getXVelocity(mActivePointerId);

                    if (getChildCount() > 0) {
                        if ((Math.abs(initialVelocity) > mMinimumVelocity)) {
@@ -480,14 +530,39 @@ public class HorizontalScrollView extends FrameLayout {
                        }
                    }
                    
                    mActivePointerId = INVALID_POINTER;
                    mIsBeingDragged = false;

                    if (mVelocityTracker != null) {
                        mVelocityTracker.recycle();
                        mVelocityTracker = null;
                    }
                }
                break;
            case MotionEvent.ACTION_POINTER_UP:
                onSecondaryPointerUp(ev);
                break;
        }
        return true;
    }
    
    private void onSecondaryPointerUp(MotionEvent ev) {
        final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >>
                MotionEvent.ACTION_POINTER_INDEX_SHIFT;
        final int pointerId = ev.getPointerId(pointerIndex);
        if (pointerId == mActivePointerId) {
            // This was our active pointer going up. Choose a new
            // active pointer and adjust accordingly.
            // TODO: Make this decision more intelligent.
            final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
            mLastMotionX = ev.getX(newPointerIndex);
            mActivePointerId = ev.getPointerId(newPointerIndex);
            if (mVelocityTracker != null) {
                mVelocityTracker.clear();
            }
        }
    }
    
    @Override
    protected void onOverscrolled(int scrollX, int scrollY,
            boolean clampedX, boolean clampedY) {
+0 −1
Original line number Diff line number Diff line
@@ -1192,7 +1192,6 @@ public class ListView extends AbsListView {
                    return mFirstPosition + i;
                }
            }
            return mFirstPosition + childCount - 1;
        }
        return INVALID_POSITION;
    }
+2 −2

File changed.

Contains only whitespace changes.