From 08adbfed3a3c291a3c9f1cb1af77dd5930a17dd1 Mon Sep 17 00:00:00 2001 From: Adam Powell Date: Wed, 10 May 2017 07:48:30 -0700 Subject: [PATCH] Lock out ResolverDrawerLayout dismissals during animations Due to views being offset during the ChooserActivity animating in direct share targets, it was possible to touch down on the sheet attempting to tap, but have it be interpreted as a fling downward as the relative touch position within the parent was moving. Lock the dismiss gesture during animations to prevent this. Bug: 36032762 Test: manual Change-Id: I18b6f03148cbf402efc23e873262927e412ea7b7 --- .../android/internal/app/ChooserActivity.java | 37 +++++++++++++++++-- .../internal/widget/ResolverDrawerLayout.java | 18 +++++++-- 2 files changed, 48 insertions(+), 7 deletions(-) diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java index df65659dface3..ece498191a18e 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -16,6 +16,8 @@ package com.android.internal.app; +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; import android.annotation.NonNull; import android.app.Activity; @@ -1136,8 +1138,10 @@ public class ChooserActivity extends ResolverActivity { * Set to true to reveal all service targets at once. */ public void setShowServiceTargets(boolean show) { - mShowServiceTargets = show; - notifyDataSetChanged(); + if (show != mShowServiceTargets) { + mShowServiceTargets = show; + notifyDataSetChanged(); + } } private void insertServiceTarget(ChooserTargetInfo chooserTargetInfo) { @@ -1201,7 +1205,18 @@ public class ChooserActivity extends ResolverActivity { return; } - mAnimator = ObjectAnimator.ofFloat(this, PROPERTY, from, to).setDuration(DURATION); + mAnimator = ObjectAnimator.ofFloat(this, PROPERTY, from, to) + .setDuration(DURATION); + mAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animation) { + mAdapter.onAnimationStart(); + } + @Override + public void onAnimationEnd(Animator animation) { + mAdapter.onAnimationEnd(); + } + }); } public RowScale setInterpolator(Interpolator interpolator) { @@ -1234,6 +1249,7 @@ public class ChooserActivity extends ResolverActivity { private final int mColumnCount = 4; private RowScale[] mServiceTargetScale; private final Interpolator mInterpolator; + private int mAnimationCount = 0; public ChooserRowAdapter(ChooserListAdapter wrappedAdapter) { mChooserListAdapter = wrappedAdapter; @@ -1302,6 +1318,21 @@ public class ChooserActivity extends ResolverActivity { return 1.f; } + public void onAnimationStart() { + final boolean lock = mAnimationCount == 0; + mAnimationCount++; + if (lock) { + mResolverDrawerLayout.setDismissLocked(true); + } + } + + public void onAnimationEnd() { + mAnimationCount--; + if (mAnimationCount == 0) { + mResolverDrawerLayout.setDismissLocked(false); + } + } + @Override public int getCount() { return (int) ( diff --git a/core/java/com/android/internal/widget/ResolverDrawerLayout.java b/core/java/com/android/internal/widget/ResolverDrawerLayout.java index e224b17ced4ab..17c7ebd396783 100644 --- a/core/java/com/android/internal/widget/ResolverDrawerLayout.java +++ b/core/java/com/android/internal/widget/ResolverDrawerLayout.java @@ -96,6 +96,8 @@ public class ResolverDrawerLayout extends ViewGroup { private OnDismissedListener mOnDismissedListener; private RunOnDismissedListener mRunOnDismissedListener; + private boolean mDismissLocked; + private float mInitialTouchX; private float mInitialTouchY; private float mLastTouchY; @@ -187,6 +189,10 @@ public class ResolverDrawerLayout extends ViewGroup { invalidate(); } + public void setDismissLocked(boolean locked) { + mDismissLocked = locked; + } + private boolean isMoving() { return mIsDragging || !mScroller.isFinished(); } @@ -229,6 +235,10 @@ public class ResolverDrawerLayout extends ViewGroup { mOnDismissedListener = listener; } + private boolean isDismissable() { + return mOnDismissedListener != null && !mDismissLocked; + } + @Override public boolean onInterceptTouchEvent(MotionEvent ev) { final int action = ev.getActionMasked(); @@ -296,7 +306,7 @@ public class ResolverDrawerLayout extends ViewGroup { mInitialTouchY = mLastTouchY = y; mActivePointerId = ev.getPointerId(0); final boolean hitView = findChildUnder(mInitialTouchX, mInitialTouchY) != null; - handled = mOnDismissedListener != null || mCollapsibleHeight > 0; + handled = isDismissable() || mCollapsibleHeight > 0; mIsDragging = hitView && handled; abortAnimation(); } @@ -348,7 +358,7 @@ public class ResolverDrawerLayout extends ViewGroup { mIsDragging = false; if (!wasDragging && findChildUnder(mInitialTouchX, mInitialTouchY) == null && findChildUnder(ev.getX(), ev.getY()) == null) { - if (mOnDismissedListener != null) { + if (isDismissable()) { dispatchOnDismissed(); resetTouch(); return true; @@ -362,7 +372,7 @@ public class ResolverDrawerLayout extends ViewGroup { mVelocityTracker.computeCurrentVelocity(1000); final float yvel = mVelocityTracker.getYVelocity(mActivePointerId); if (Math.abs(yvel) > mMinFlingVelocity) { - if (mOnDismissedListener != null + if (isDismissable() && yvel > 0 && mCollapseOffset > mCollapsibleHeight) { smoothScrollTo(mCollapsibleHeight + mUncollapsibleHeight, yvel); mDismissOnScrollerFinished = true; @@ -656,7 +666,7 @@ public class ResolverDrawerLayout extends ViewGroup { @Override public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed) { if (!consumed && Math.abs(velocityY) > mMinFlingVelocity) { - if (mOnDismissedListener != null + if (isDismissable() && velocityY < 0 && mCollapseOffset > mCollapsibleHeight) { smoothScrollTo(mCollapsibleHeight + mUncollapsibleHeight, velocityY); mDismissOnScrollerFinished = true;