Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Any solution for scrollToPosition() bug? #24

Open
polaris0227 opened this issue Apr 17, 2018 · 2 comments
Open

Any solution for scrollToPosition() bug? #24

polaris0227 opened this issue Apr 17, 2018 · 2 comments

Comments

@polaris0227
Copy link

No description provided.

@MohamedElshafey
Copy link

MohamedElshafey commented Oct 30, 2018

I make a small hack to solve this problem

go to EndlessLoopAdapterContainer.java

and replace onTouchEvent() function by this snippet

public boolean onTouchEvent(MotionEvent event) {
    if (mAdapter == null) {
        return false;
    }
    if (mVelocityTracker == null) {
        mVelocityTracker = VelocityTracker.obtain();
    }
    mVelocityTracker.addMovement(event);

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


    switch (action) {
        case MotionEvent.ACTION_DOWN:
            super.onTouchEvent(event);
            /*
             * If being flinged and user touches, stop the fling. isFinished
             * will be false if being flinged.
             */
            if (!mScroller.isFinished()) {
                mScroller.forceFinished(true);
            }

            downX = (int) x;
            // Remember where the motion event started
            mLastMotionX = x;
            mLastMotionY = y;

            break;
        case MotionEvent.ACTION_MOVE:
            //if we have scrolling disabled, we don't do anything
            if (!shouldRepeat && isSrollingDisabled) return false;

            if (mTouchState == TOUCH_STATE_SCROLLING) {
                // Scroll to follow the motion event
                final int deltaX = (int) (mLastMotionX - x);
                mLastMotionX = x;
                mLastMotionY = y;

                int sx = getScrollX() + deltaX;

                if (downX > x) {
                    scrollBy(5, 0);
                } else {
                    scrollBy(-5, 0);
                }
                downX = (int) x;

            } else {
                final int xDiff = (int) Math.abs(x - mLastMotionX);

                final int touchSlop = mTouchSlop;
                final boolean xMoved = xDiff > touchSlop;


                if (xMoved) {

                    // Scroll if the user moved far enough along the X axis
                    mTouchState = TOUCH_STATE_SCROLLING;
                    enableChildrenCache();

                    // Either way, cancel any pending longpress
                    if (mAllowLongPress) {
                        mAllowLongPress = false;
                        // Try canceling the long press. It could also have been scheduled
                        // by a distant descendant, so use the mAllowLongPress flag to block
                        // everything
                        cancelLongPress();
                    }
                }
            }
            break;
        case MotionEvent.ACTION_UP:

            //this must be here, in case no child view returns true,
            //events will propagate back here and on intercept touch event wont be called again
            //in case of no parent it propagates here, in case of parent it usualy propagates to on cancel
            if (mHandleSelectionOnActionUp && mTouchState == TOUCH_STATE_RESTING) {
                final float d = ToolBox.getLineLength(mDown.x, mDown.y, x, y);
                if ((event.getEventTime() - event.getDownTime()) < ViewConfiguration.getLongPressTimeout() && d < mTouchSlop)
                    handleClick(mDown);
                mHandleSelectionOnActionUp = false;
            }

            //if we had normal down click and we haven't moved enough to initiate drag, take action as a click on down coordinates
            if (mTouchState == TOUCH_STATE_SCROLLING) {

                mVelocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
                int initialXVelocity = (int) mVelocityTracker.getXVelocity();
                int initialYVelocity = (int) mVelocityTracker.getYVelocity();

                if (Math.abs(initialXVelocity) + Math.abs(initialYVelocity) > mMinimumVelocity) {
                    fling(-initialXVelocity, -initialYVelocity);
                } else {
                    // Release the drag
                    clearChildrenCache();
                    mTouchState = TOUCH_STATE_RESTING;
                    checkScrollPosition();
                    mAllowLongPress = false;

                    mDown.x = -1;
                    mDown.y = -1;
                }

                if (mVelocityTracker != null) {
                    mVelocityTracker.recycle();
                    mVelocityTracker = null;
                }

                break;
            }

            // Release the drag
            clearChildrenCache();
            mTouchState = TOUCH_STATE_RESTING;
            mAllowLongPress = false;

            mDown.x = -1;
            mDown.y = -1;

            break;
        case MotionEvent.ACTION_CANCEL:          

            mAllowLongPress = false;

            mDown.x = -1;
            mDown.y = -1;

            if (mTouchState == TOUCH_STATE_SCROLLING) {
                if (checkScrollPosition()) {
                    break;
                }
            }

            mTouchState = TOUCH_STATE_RESTING;
    }

    return true;
}

@ArcherEmiya05
Copy link

I make a small hack to solve this problem

go to EndlessLoopAdapterContainer.java

and replace onTouchEvent() function by this snippet

public boolean onTouchEvent(MotionEvent event) {
    if (mAdapter == null) {
        return false;
    }
    if (mVelocityTracker == null) {
        mVelocityTracker = VelocityTracker.obtain();
    }
    mVelocityTracker.addMovement(event);

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


    switch (action) {
        case MotionEvent.ACTION_DOWN:
            super.onTouchEvent(event);
            /*
             * If being flinged and user touches, stop the fling. isFinished
             * will be false if being flinged.
             */
            if (!mScroller.isFinished()) {
                mScroller.forceFinished(true);
            }

            downX = (int) x;
            // Remember where the motion event started
            mLastMotionX = x;
            mLastMotionY = y;

            break;
        case MotionEvent.ACTION_MOVE:
            //if we have scrolling disabled, we don't do anything
            if (!shouldRepeat && isSrollingDisabled) return false;

            if (mTouchState == TOUCH_STATE_SCROLLING) {
                // Scroll to follow the motion event
                final int deltaX = (int) (mLastMotionX - x);
                mLastMotionX = x;
                mLastMotionY = y;

                int sx = getScrollX() + deltaX;

                if (downX > x) {
                    scrollBy(5, 0);
                } else {
                    scrollBy(-5, 0);
                }
                downX = (int) x;

            } else {
                final int xDiff = (int) Math.abs(x - mLastMotionX);

                final int touchSlop = mTouchSlop;
                final boolean xMoved = xDiff > touchSlop;


                if (xMoved) {

                    // Scroll if the user moved far enough along the X axis
                    mTouchState = TOUCH_STATE_SCROLLING;
                    enableChildrenCache();

                    // Either way, cancel any pending longpress
                    if (mAllowLongPress) {
                        mAllowLongPress = false;
                        // Try canceling the long press. It could also have been scheduled
                        // by a distant descendant, so use the mAllowLongPress flag to block
                        // everything
                        cancelLongPress();
                    }
                }
            }
            break;
        case MotionEvent.ACTION_UP:

            //this must be here, in case no child view returns true,
            //events will propagate back here and on intercept touch event wont be called again
            //in case of no parent it propagates here, in case of parent it usualy propagates to on cancel
            if (mHandleSelectionOnActionUp && mTouchState == TOUCH_STATE_RESTING) {
                final float d = ToolBox.getLineLength(mDown.x, mDown.y, x, y);
                if ((event.getEventTime() - event.getDownTime()) < ViewConfiguration.getLongPressTimeout() && d < mTouchSlop)
                    handleClick(mDown);
                mHandleSelectionOnActionUp = false;
            }

            //if we had normal down click and we haven't moved enough to initiate drag, take action as a click on down coordinates
            if (mTouchState == TOUCH_STATE_SCROLLING) {

                mVelocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
                int initialXVelocity = (int) mVelocityTracker.getXVelocity();
                int initialYVelocity = (int) mVelocityTracker.getYVelocity();

                if (Math.abs(initialXVelocity) + Math.abs(initialYVelocity) > mMinimumVelocity) {
                    fling(-initialXVelocity, -initialYVelocity);
                } else {
                    // Release the drag
                    clearChildrenCache();
                    mTouchState = TOUCH_STATE_RESTING;
                    checkScrollPosition();
                    mAllowLongPress = false;

                    mDown.x = -1;
                    mDown.y = -1;
                }

                if (mVelocityTracker != null) {
                    mVelocityTracker.recycle();
                    mVelocityTracker = null;
                }

                break;
            }

            // Release the drag
            clearChildrenCache();
            mTouchState = TOUCH_STATE_RESTING;
            mAllowLongPress = false;

            mDown.x = -1;
            mDown.y = -1;

            break;
        case MotionEvent.ACTION_CANCEL:          

            mAllowLongPress = false;

            mDown.x = -1;
            mDown.y = -1;

            if (mTouchState == TOUCH_STATE_SCROLLING) {
                if (checkScrollPosition()) {
                    break;
                }
            }

            mTouchState = TOUCH_STATE_RESTING;
    }

    return true;
}

Where did you get downX?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants