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

Commit 5dd072d8 authored by Adam Powell's avatar Adam Powell
Browse files

Allow swipe down to dismiss for ResolverDrawerLayout

Let the user swipe the intent resolver UI off of the screen to get rid
of it. So satisfying!

Also fix a bug where transitioning between touching the area outside
of the drawer to the drawer itself would misbehave or otherwise
dismiss when it shouldn't.

Bug 18026675

Change-Id: I456cc22b9575dc4c65e45154dc81201fe2045adc
parent 685a8770
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -278,9 +278,9 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic

        final ResolverDrawerLayout rdl = (ResolverDrawerLayout) findViewById(R.id.contentPanel);
        if (rdl != null) {
            rdl.setOnClickOutsideListener(new View.OnClickListener() {
            rdl.setOnDismissedListener(new ResolverDrawerLayout.OnDismissedListener() {
                @Override
                public void onClick(View v) {
                public void onDismissed() {
                    finish();
                }
            });
+59 −21
Original line number Diff line number Diff line
@@ -63,18 +63,22 @@ public class ResolverDrawerLayout extends ViewGroup {
    private float mCollapseOffset;

    private int mCollapsibleHeight;
    private int mUncollapsibleHeight;

    private int mTopOffset;

    private boolean mIsDragging;
    private boolean mOpenOnClick;
    private boolean mOpenOnLayout;
    private boolean mDismissOnScrollerFinished;
    private final int mTouchSlop;
    private final float mMinFlingVelocity;
    private final OverScroller mScroller;
    private final VelocityTracker mVelocityTracker;

    private OnClickListener mClickOutsideListener;
    private OnDismissedListener mOnDismissedListener;
    private RunOnDismissedListener mRunOnDismissedListener;

    private float mInitialTouchX;
    private float mInitialTouchY;
    private float mLastTouchY;
@@ -143,8 +147,8 @@ public class ResolverDrawerLayout extends ViewGroup {
        return isSmallCollapsed() ? mMaxCollapsedHeightSmall : mMaxCollapsedHeight;
    }

    public void setOnClickOutsideListener(OnClickListener listener) {
        mClickOutsideListener = listener;
    public void setOnDismissedListener(OnDismissedListener listener) {
        mOnDismissedListener = listener;
    }

    @Override
@@ -194,7 +198,7 @@ public class ResolverDrawerLayout extends ViewGroup {
        }

        if (mIsDragging) {
            mScroller.abortAnimation();
            abortAnimation();
        }
        return mIsDragging || mOpenOnClick;
    }
@@ -213,12 +217,9 @@ public class ResolverDrawerLayout extends ViewGroup {
                mInitialTouchX = x;
                mInitialTouchY = mLastTouchY = y;
                mActivePointerId = ev.getPointerId(0);
                if (findChildUnder(mInitialTouchX, mInitialTouchY) == null &&
                        mClickOutsideListener != null) {
                    mIsDragging = handled = true;
                }
                handled |= mCollapsibleHeight > 0;
                mScroller.abortAnimation();
                mIsDragging = findChildUnder(mInitialTouchX, mInitialTouchY) != null;
                handled = (!mIsDragging && mOnDismissedListener != null) || mCollapsibleHeight > 0;
                abortAnimation();
            }
            break;

@@ -264,11 +265,12 @@ public class ResolverDrawerLayout extends ViewGroup {
            break;

            case MotionEvent.ACTION_UP: {
                final boolean wasDragging = mIsDragging;
                mIsDragging = false;
                if (!mIsDragging && findChildUnder(mInitialTouchX, mInitialTouchY) == null &&
                if (!wasDragging && findChildUnder(mInitialTouchX, mInitialTouchY) == null &&
                        findChildUnder(ev.getX(), ev.getY()) == null) {
                    if (mClickOutsideListener != null) {
                        mClickOutsideListener.onClick(this);
                    if (mOnDismissedListener != null) {
                        dispatchOnDismissed();
                        resetTouch();
                        return true;
                    }
@@ -281,7 +283,13 @@ public class ResolverDrawerLayout extends ViewGroup {
                mVelocityTracker.computeCurrentVelocity(1000);
                final float yvel = mVelocityTracker.getYVelocity(mActivePointerId);
                if (Math.abs(yvel) > mMinFlingVelocity) {
                    if (mOnDismissedListener != null
                            && yvel > 0 && mCollapseOffset > mCollapsibleHeight) {
                        smoothScrollTo(mCollapsibleHeight + mUncollapsibleHeight, yvel);
                        mDismissOnScrollerFinished = true;
                    } else {
                        smoothScrollTo(yvel < 0 ? 0 : mCollapsibleHeight, yvel);
                    }
                } else {
                    smoothScrollTo(
                            mCollapseOffset < mCollapsibleHeight / 2 ? 0 : mCollapsibleHeight, 0);
@@ -327,17 +335,27 @@ public class ResolverDrawerLayout extends ViewGroup {
    @Override
    public void computeScroll() {
        super.computeScroll();
        if (!mScroller.isFinished()) {
            final boolean keepGoing = mScroller.computeScrollOffset();
        if (mScroller.computeScrollOffset()) {
            final boolean keepGoing = !mScroller.isFinished();
            performDrag(mScroller.getCurrY() - mCollapseOffset);
            if (keepGoing) {
                postInvalidateOnAnimation();
            } else if (mDismissOnScrollerFinished && mOnDismissedListener != null) {
                mRunOnDismissedListener = new RunOnDismissedListener();
                post(mRunOnDismissedListener);
            }
        }
    }

    private void abortAnimation() {
        mScroller.abortAnimation();
        mRunOnDismissedListener = null;
        mDismissOnScrollerFinished = false;
    }

    private float performDrag(float dy) {
        final float newPos = Math.max(0, Math.min(mCollapseOffset + dy, mCollapsibleHeight));
        final float newPos = Math.max(0, Math.min(mCollapseOffset + dy,
                mCollapsibleHeight + mUncollapsibleHeight));
        if (newPos != mCollapseOffset) {
            dy = newPos - mCollapseOffset;
            final int childCount = getChildCount();
@@ -356,11 +374,18 @@ public class ResolverDrawerLayout extends ViewGroup {
        return 0;
    }

    private void smoothScrollTo(int yOffset, float velocity) {
        if (getMaxCollapsedHeight() == 0) {
            return;
    void dispatchOnDismissed() {
        if (mOnDismissedListener != null) {
            mOnDismissedListener.onDismissed();
        }
        mScroller.abortAnimation();
        if (mRunOnDismissedListener != null) {
            removeCallbacks(mRunOnDismissedListener);
            mRunOnDismissedListener = null;
        }
    }

    private void smoothScrollTo(int yOffset, float velocity) {
        abortAnimation();
        final int sy = (int) mCollapseOffset;
        int dy = yOffset - sy;
        if (dy == 0) {
@@ -490,6 +515,7 @@ public class ResolverDrawerLayout extends ViewGroup {
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        getViewTreeObserver().removeOnTouchModeChangeListener(mTouchModeChangeListener);
        abortAnimation();
    }

    @Override
@@ -585,6 +611,7 @@ public class ResolverDrawerLayout extends ViewGroup {

        mCollapsibleHeight = Math.max(0,
                heightUsed - alwaysShowHeight - getMaxCollapsedHeight());
        mUncollapsibleHeight = heightUsed - mCollapsibleHeight;

        if (isLaidOut()) {
            mCollapseOffset = Math.min(mCollapseOffset, mCollapsibleHeight);
@@ -734,4 +761,15 @@ public class ResolverDrawerLayout extends ViewGroup {
            }
        };
    }

    public interface OnDismissedListener {
        public void onDismissed();
    }

    private class RunOnDismissedListener implements Runnable {
        @Override
        public void run() {
            dispatchOnDismissed();
        }
    }
}