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

Commit 21b7571b authored by Hyunyoung Song's avatar Hyunyoung Song
Browse files

Get rid of CATCH state in verticalpulldetector

> There was a bug regarding mLastDisplacement not being cleared out, which
caused a jump of the all apps container.
> Also as a cleanup, got rid of the CATCH state.

Change-Id: Iae9af0be04cce15f2ba4e6734d1615f879921e5d
parent b1e9e8d6
Loading
Loading
Loading
Loading
+19 −17
Original line number Diff line number Diff line
@@ -11,7 +11,6 @@ import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;

import com.android.launcher3.CellLayout;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Hotseat;
import com.android.launcher3.Launcher;
@@ -100,31 +99,34 @@ public class AllAppsTransitionController implements TouchController, VerticalPul
            } else {
                // Now figure out which direction scroll events the controller will start
                // calling the callbacks.
                int conditionsToReportScroll = 0;
                int directionsToDetectScroll = 0;
                boolean ignoreSlopWhenSettling = false;

                if (mDetector.isRestingState()) {
                if (mDetector.isIdleState()) {
                    if (mLauncher.isAllAppsVisible()) {
                        conditionsToReportScroll |= VerticalPullDetector.THRESHOLD_DOWN;
                        directionsToDetectScroll |= VerticalPullDetector.DIRECTION_DOWN;
                    } else {
                        conditionsToReportScroll |= VerticalPullDetector.THRESHOLD_UP;
                        directionsToDetectScroll |= VerticalPullDetector.DIRECTION_UP;
                    }
                } else {
                    if (isInDisallowRecatchBottomZone()) {
                        conditionsToReportScroll |= VerticalPullDetector.THRESHOLD_UP;
                        directionsToDetectScroll |= VerticalPullDetector.DIRECTION_UP;
                    } else if (isInDisallowRecatchTopZone()) {
                        conditionsToReportScroll |= VerticalPullDetector.THRESHOLD_DOWN;
                        directionsToDetectScroll |= VerticalPullDetector.DIRECTION_DOWN;
                    } else {
                        conditionsToReportScroll |= VerticalPullDetector.THRESHOLD_ONLY;
                        directionsToDetectScroll |= VerticalPullDetector.DIRECTION_BOTH;
                        ignoreSlopWhenSettling = true;
                    }
                }
                mDetector.setDetectableScrollConditions(conditionsToReportScroll);
                mDetector.setDetectableScrollConditions(directionsToDetectScroll,
                        ignoreSlopWhenSettling);
            }
        }
        if (mNoIntercept) {
            return false;
        }
        mDetector.onTouchEvent(ev);
        if (mDetector.isScrollingState() && (isInDisallowRecatchBottomZone() || isInDisallowRecatchTopZone())) {
        if (mDetector.isSettlingState() && (isInDisallowRecatchBottomZone() || isInDisallowRecatchTopZone())) {
            return false;
        }
        return mDetector.shouldIntercept();
@@ -132,7 +134,7 @@ public class AllAppsTransitionController implements TouchController, VerticalPul

    private boolean shouldPossiblyIntercept(MotionEvent ev) {
        DeviceProfile grid = mLauncher.getDeviceProfile();
        if (mDetector.isRestingState()) {
        if (mDetector.isIdleState()) {
            if (grid.isVerticalBarLayout()) {
                if (ev.getY() > mLauncher.getDeviceProfile().heightPx - mBezelSwipeUpHeight) {
                    return true;
@@ -164,7 +166,7 @@ public class AllAppsTransitionController implements TouchController, VerticalPul
    }

    @Override
    public void onScrollStart(boolean start) {
    public void onDragStart(boolean start) {
        cancelAnimation();
        mCurrentAnimation = LauncherAnimUtils.createAnimatorSet();
        mShiftStart = mAppsView.getTranslationY();
@@ -172,7 +174,7 @@ public class AllAppsTransitionController implements TouchController, VerticalPul
    }

    @Override
    public boolean onScroll(float displacement, float velocity) {
    public boolean onDrag(float displacement, float velocity) {
        if (mAppsView == null) {
            return false;   // early termination.
        }
@@ -182,7 +184,7 @@ public class AllAppsTransitionController implements TouchController, VerticalPul
    }

    @Override
    public void onScrollEnd(float velocity, boolean fling) {
    public void onDragEnd(float velocity, boolean fling) {
        if (mAppsView == null) {
            return; // early termination.
        }
@@ -229,7 +231,7 @@ public class AllAppsTransitionController implements TouchController, VerticalPul
     */
    public void preparePull(boolean start) {
        if (start) {
            // Initialize values that should not change until #onScrollEnd
            // Initialize values that should not change until #onDragEnd
            mStatusBarHeight = mLauncher.getDragLayer().getInsets().top;
            mHotseat.setVisibility(View.VISIBLE);
            mHotseat.bringToFront();
@@ -321,7 +323,7 @@ public class AllAppsTransitionController implements TouchController, VerticalPul
        if (animationOut == null){
            return;
        }
        if (mDetector.isRestingState()) {
        if (mDetector.isIdleState()) {
            preparePull(true);
            mAnimationDuration = duration;
            mShiftStart = mAppsView.getTranslationY();
@@ -361,7 +363,7 @@ public class AllAppsTransitionController implements TouchController, VerticalPul
        if (animationOut == null){
            return;
        }
        if(mDetector.isRestingState()) {
        if(mDetector.isIdleState()) {
            preparePull(true);
            mAnimationDuration = duration;
            mShiftStart = mAppsView.getTranslationY();
+69 −54
Original line number Diff line number Diff line
@@ -18,10 +18,10 @@ public class VerticalPullDetector {

    private float mTouchSlop;

    private int mScrollDirections;
    public static final int THRESHOLD_UP = 1 << 0;
    public static final int THRESHOLD_DOWN = 1 << 1;
    public static final int THRESHOLD_ONLY = THRESHOLD_DOWN | THRESHOLD_UP;
    private int mScrollConditions;
    public static final int DIRECTION_UP = 1 << 0;
    public static final int DIRECTION_DOWN = 1 << 1;
    public static final int DIRECTION_BOTH = DIRECTION_DOWN | DIRECTION_UP;


    /**
@@ -36,42 +36,54 @@ public class VerticalPullDetector {
    public static final float SCROLL_VELOCITY_DAMPENING_RC = 1000f / (2f * (float) Math.PI * 10);

    /* Scroll state, this is set to true during dragging and animation. */
    private State mState = State.NONE;
    private ScrollState mState = ScrollState.IDLE;

    enum State {
        NONE,
        CATCH,          // onScrollStart
        DRAG,           // onScrollStart, onScroll
        SCROLLING       // onScrollEnd
    enum ScrollState {
        IDLE,
        DRAGGING,      // onDragStart, onDrag
        SETTLING       // onDragEnd
    };

    //------------------- State transition diagram -----------------------------------
    //------------------- ScrollState transition diagram -----------------------------------
    //
    // NONE -> (mDisplacement > mTouchSlop) -> DRAG
    // DRAG -> (MotionEvent#ACTION_UP, MotionEvent#ACTION_CANCEL) -> SCROLLING
    // SCROLLING -> (MotionEvent#ACTION_DOWN) && (mDisplacement > mTouchSlop) -> CATCH
    // SCROLLING -> (View settled) -> NONE
    // IDLE ->      (mDisplacement > mTouchSlop) -> DRAGGING
    // DRAGGING -> (MotionEvent#ACTION_UP, MotionEvent#ACTION_CANCEL) -> SETTLING
    // SETTLING -> (MotionEvent#ACTION_DOWN) -> DRAGGING
    // SETTLING -> (View settled) -> IDLE

    private void setState(State newState) {
    private void setState(ScrollState newState) {
        if (DBG) {
            Log.d(TAG, "setState:" + mState + "->" + newState);
        }
        // onDragStart and onDragEnd is reported ONLY on state transition
        if (newState == ScrollState.DRAGGING) {
            initializeDragging();
            if (mState == ScrollState.IDLE) {
                reportDragStart(false /* recatch */);
            } else if (mState == ScrollState.SETTLING) {
                reportDragStart(true /* recatch */);
            }
        }
        if (newState == ScrollState.SETTLING) {
            reportDragEnd();
        }

        mState = newState;
    }

    public boolean shouldIntercept() {
        return mState == State.DRAG || mState == State.SCROLLING || mState == State.CATCH;
        return mState == ScrollState.DRAGGING || mState == ScrollState.SETTLING;
    }

    /**
     * There's no touch and there's no animation.
     */
    public boolean isRestingState() {
        return mState == State.NONE;
    public boolean isIdleState() {
        return mState == ScrollState.IDLE;
    }

    public boolean isScrollingState() {
        return mState == State.SCROLLING;
    public boolean isSettlingState() {
        return mState == ScrollState.SETTLING;
    }

    private float mDownX;
@@ -87,6 +99,7 @@ public class VerticalPullDetector {
    private float mDisplacementX;

    private float mSubtractDisplacement;
    private boolean mIgnoreSlopWhenSettling;

    /* Client of this gesture detector can register a callback. */
    Listener mListener;
@@ -96,17 +109,18 @@ public class VerticalPullDetector {
    }

    interface Listener{
        void onScrollStart(boolean start);
        boolean onScroll(float displacement, float velocity);
        void onScrollEnd(float velocity, boolean fling);
        void onDragStart(boolean start);
        boolean onDrag(float displacement, float velocity);
        void onDragEnd(float velocity, boolean fling);
    }

    public VerticalPullDetector(Context context) {
        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
    }

    public void setDetectableScrollConditions(int scrollDirectionFlags) {
        mScrollDirections = scrollDirectionFlags;
    public void setDetectableScrollConditions(int scrollDirectionFlags, boolean ignoreSlop) {
        mScrollConditions = scrollDirectionFlags;
        mIgnoreSlopWhenSettling = ignoreSlop;
    }

    private boolean shouldScrollStart() {
@@ -122,8 +136,8 @@ public class VerticalPullDetector {
            return false;
        }
        // Check if the client is interested in scroll in current direction.
        if (((mScrollDirections & THRESHOLD_DOWN) > 0 && mDisplacementY > 0) ||
            ((mScrollDirections & THRESHOLD_UP) > 0 && mDisplacementY < 0)) {
        if (((mScrollConditions & DIRECTION_DOWN) > 0 && mDisplacementY > 0) ||
            ((mScrollConditions & DIRECTION_UP) > 0 && mDisplacementY < 0)) {
            return true;
        }
        return false;
@@ -136,12 +150,11 @@ public class VerticalPullDetector {
                mDownX = ev.getX();
                mDownY = ev.getY();
                mLastDisplacement = 0;
                mDisplacementY = 0;
                mVelocity = 0;

                // handle state and listener calls.
                if (mState == State.SCROLLING && shouldScrollStart()){
                    reportScrollStart(true /* recatch */);
                    setState(State.CATCH);
                if (mState == ScrollState.SETTLING && mIgnoreSlopWhenSettling) {
                    setState(ScrollState.DRAGGING);
                }
                break;
            case MotionEvent.ACTION_MOVE:
@@ -150,22 +163,18 @@ public class VerticalPullDetector {
                mVelocity = computeVelocity(ev, mVelocity);

                // handle state and listener calls.
                if (shouldScrollStart() && mState != State.DRAG) {
                    if (mState == State.NONE) {
                        reportScrollStart(false /* recatch */);
                    }
                    setState(State.DRAG);
                if (mState != ScrollState.DRAGGING && shouldScrollStart()) {
                    setState(ScrollState.DRAGGING);
                }
                if (mState == State.DRAG) {
                    reportScroll();
                if (mState == ScrollState.DRAGGING) {
                    reportDragging();
                }
                break;
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                // These are synthetic events and there is no need to update internal values.
                if (mState == State.DRAG || mState == State.CATCH) {
                    reportScrollEnd();
                    setState(State.SCROLLING);
                if (mState == ScrollState.DRAGGING) {
                    setState(ScrollState.SETTLING);
                }
                break;
            default:
@@ -182,41 +191,47 @@ public class VerticalPullDetector {
    }

    public void finishedScrolling() {
        setState(State.NONE);
        setState(ScrollState.IDLE);
    }

    private boolean reportScrollStart(boolean recatch) {
        mListener.onScrollStart(!recatch);
    private boolean reportDragStart(boolean recatch) {
        mListener.onDragStart(!recatch);
        if (DBG) {
            Log.d(TAG, "onDragStart recatch:" + recatch);
        }
        return true;
    }

    private void initializeDragging() {
        if (mState == ScrollState.SETTLING && mIgnoreSlopWhenSettling) {
            mSubtractDisplacement = 0;
        }
        if (mDisplacementY > 0) {
            mSubtractDisplacement = mTouchSlop;
        } else {
            mSubtractDisplacement = -mTouchSlop;
        }
        if (DBG) {
            Log.d(TAG, "onScrollStart recatch:" + recatch);
        }
        return true;
    }

    private boolean reportScroll() {
    private boolean reportDragging() {
        float delta = mDisplacementY - mLastDisplacement;
        if (delta != 0) {
            if (DBG) {
                Log.d(TAG, String.format("onScroll disp=%.1f, velocity=%.1f",
                Log.d(TAG, String.format("onDrag disp=%.1f, velocity=%.1f",
                        mDisplacementY, mVelocity));
            }

            return mListener.onScroll(mDisplacementY - mSubtractDisplacement, mVelocity);
            return mListener.onDrag(mDisplacementY - mSubtractDisplacement, mVelocity);
        }
        return true;
    }

    private void reportScrollEnd() {
    private void reportDragEnd() {
        if (DBG) {
            Log.d(TAG, String.format("onScrolEnd disp=%.1f, velocity=%.1f",
                    mDisplacementY, mVelocity));
        }
        mListener.onScrollEnd(mVelocity, Math.abs(mVelocity) > RELEASE_VELOCITY_PX_MS);
        mListener.onDragEnd(mVelocity, Math.abs(mVelocity) > RELEASE_VELOCITY_PX_MS);

    }
    /**