Ensure forwarding listener target is long-clickable
Also synchronizes with bug fixes in framework version.
Bug: 28550349
Change-Id: I5ba37d75bdb117aa6edbc14b151fc61c4ad96453
diff --git a/v7/appcompat/src/android/support/v7/widget/ForwardingListener.java b/v7/appcompat/src/android/support/v7/widget/ForwardingListener.java
index 7d53b93..3e4d063 100644
--- a/v7/appcompat/src/android/support/v7/widget/ForwardingListener.java
+++ b/v7/appcompat/src/android/support/v7/widget/ForwardingListener.java
@@ -16,13 +16,16 @@
package android.support.v7.widget;
+import android.os.Build;
import android.os.SystemClock;
import android.support.v4.view.MotionEventCompat;
import android.support.v7.view.menu.ShowableListMenu;
import android.view.MotionEvent;
import android.view.View;
+import android.view.View.OnAttachStateChangeListener;
import android.view.ViewConfiguration;
import android.view.ViewParent;
+import android.view.ViewTreeObserver.OnGlobalLayoutListener;
/**
@@ -31,6 +34,7 @@
* @hide
*/
public abstract class ForwardingListener implements View.OnTouchListener {
+
/** Scaled touch slop, used for detecting movement outside bounds. */
private final float mScaledTouchSlop;
@@ -62,12 +66,48 @@
public ForwardingListener(View src) {
mSrc = src;
+ src.setLongClickable(true);
+
+ if (Build.VERSION.SDK_INT >= 12) {
+ addDetachListenerApi12(src);
+ } else {
+ addDetachListenerBase(src);
+ }
+
mScaledTouchSlop = ViewConfiguration.get(src.getContext()).getScaledTouchSlop();
mTapTimeout = ViewConfiguration.getTapTimeout();
+
// Use a medium-press timeout. Halfway between tap and long-press.
mLongPressTimeout = (mTapTimeout + ViewConfiguration.getLongPressTimeout()) / 2;
}
+ private void addDetachListenerApi12(View src) {
+ src.addOnAttachStateChangeListener(new OnAttachStateChangeListener() {
+ @Override
+ public void onViewAttachedToWindow(View v) {}
+
+ @Override
+ public void onViewDetachedFromWindow(View v) {
+ onDetachedFromWindow();
+ }
+ });
+ }
+
+ private void addDetachListenerBase(View src) {
+ src.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
+ boolean mIsAttached = mSrc.isAttachedToWindow();
+
+ @Override
+ public void onGlobalLayout() {
+ final boolean wasAttached = mIsAttached;
+ mIsAttached = mSrc.isAttachedToWindow();
+ if (wasAttached && !mIsAttached) {
+ onDetachedFromWindow();
+ }
+ }
+ });
+ }
+
/**
* Returns the popup to which this listener is forwarding events.
* <p>
@@ -103,6 +143,15 @@
return forwarding || wasForwarding;
}
+ private void onDetachedFromWindow() {
+ mForwarding = false;
+ mActivePointerId = MotionEvent.INVALID_POINTER_ID;
+
+ if (mDisallowIntercept != null) {
+ mSrc.removeCallbacks(mDisallowIntercept);
+ }
+ }
+
/**
* Called when forwarding would like to start.
* <p>