Skip to content

Commit

Permalink
fix(android): longpress event wrongly fires on a tapped view with tou…
Browse files Browse the repository at this point in the history
…ch disabled (#12825)

Fixes TIMOB-28454
  • Loading branch information
build authored May 24, 2021
1 parent eab635f commit 5ac477c
Showing 1 changed file with 53 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@
import android.view.View.OnClickListener;
import android.view.View.OnFocusChangeListener;
import android.view.View.OnKeyListener;
import android.view.View.OnLongClickListener;
import android.view.View.OnTouchListener;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
Expand Down Expand Up @@ -132,7 +132,9 @@ public TiBackgroundDrawable getBackground()
private float animatedRotationDegrees = 0f; // i.e., no rotation.
private float animatedAlpha = Float.MIN_VALUE; // i.e., no animated alpha.

protected KrollDict lastUpEvent = new KrollDict(2);
protected KrollDict lastUpEvent = new KrollDict(3);
private MotionEvent longPressMotionEvent;

// In the case of heavy-weight windows, the "nativeView" is null,
// so this holds a reference to the view which is used for touching,
// i.e., the view passed to registerForTouch.
Expand Down Expand Up @@ -1293,6 +1295,7 @@ public void release()
if (Log.isDebugModeEnabled()) {
Log.d(TAG, "Releasing: " + this, Log.DEBUG_MODE);
}
releaseLongPressMotionEvent();
View nv = getNativeView();
if (nv != null) {
if (nv instanceof ViewGroup) {
Expand Down Expand Up @@ -1336,6 +1339,14 @@ public void release()
layoutParams = null;
}

private void releaseLongPressMotionEvent()
{
if (this.longPressMotionEvent != null) {
this.longPressMotionEvent.recycle();
this.longPressMotionEvent = null;
}
}

private void setVisibility(int visibility)
{
if (visibility == View.INVISIBLE) {
Expand Down Expand Up @@ -1744,23 +1755,21 @@ public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float ve
}
return false;
}

@Override
public void onLongPress(MotionEvent e)
{
Log.d(TAG, "LONGPRESS on " + proxy, Log.DEBUG_MODE);

if (proxy != null && proxy.hierarchyHasListener(TiC.EVENT_LONGPRESS)) {
fireEvent(TiC.EVENT_LONGPRESS, dictFromEvent(e));
}
}
});
detector.setIsLongpressEnabled(false); // We do our own "longpress" detection via onTouch().

touchable.setOnTouchListener(new OnTouchListener() {
int pointersDown = 0;
int touchSlop;

public boolean onTouch(View view, MotionEvent event)
{
// Fetch max distance finger can travel until it can't be considered a click/tap.
if (this.touchSlop <= 0) {
this.touchSlop = ViewConfiguration.get(view.getContext()).getScaledTouchSlop();
}

// Store position where touch was released for the onClick() listener.
if (event.getAction() == MotionEvent.ACTION_UP) {
TiDimension xDimension = new TiDimension((double) event.getX(), TiDimension.TYPE_LEFT);
TiDimension yDimension = new TiDimension((double) event.getY(), TiDimension.TYPE_TOP);
Expand All @@ -1769,6 +1778,31 @@ public boolean onTouch(View view, MotionEvent event)
lastUpEvent.put(TiC.EVENT_PROPERTY_OBSCURED, wasObscured(event));
}

// Do custom "longpress" event tracking. Store motion event data to be used by onLongClick() listener.
// Note: Can't use GestureDetector for this since we would have to handle onDown() to make it work,
// which would prevent view's onClick() and onLongClick() listeners from being called.
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// Start tracking.
releaseLongPressMotionEvent();
longPressMotionEvent = MotionEvent.obtain(event);
break;
case MotionEvent.ACTION_MOVE:
// Stop tracking if dragged too far from initial touch point.
if (longPressMotionEvent != null) {
float deltaX = Math.abs(longPressMotionEvent.getRawX() - event.getRawX());
float deltaY = Math.abs(longPressMotionEvent.getRawY() - event.getRawY());
if ((deltaX > this.touchSlop) || (deltaY > this.touchSlop)) {
releaseLongPressMotionEvent();
}
}
break;
default:
// Stop tracking on ACTION_UP, ACTION_CANCEL, etc.
releaseLongPressMotionEvent();
break;
}

if (proxy != null && proxy.hierarchyHasListener(TiC.EVENT_PINCH)) {
scaleDetector.onTouchEvent(event);
if (scaleDetector.isInProgress()) {
Expand Down Expand Up @@ -2090,11 +2124,14 @@ public boolean fireSyncEvent(String eventName, KrollDict data, boolean bubbles)

protected void setOnLongClickListener(View view)
{
view.setOnLongClickListener(new OnLongClickListener() {
public boolean onLongClick(View view)
{
return fireEvent(TiC.EVENT_LONGCLICK, null);
view.setOnLongClickListener((View v) -> {
boolean wasHandled = false;
if (this.longPressMotionEvent != null) {
wasHandled = fireEvent(TiC.EVENT_LONGPRESS, dictFromEvent(this.longPressMotionEvent));
releaseLongPressMotionEvent();
}
wasHandled |= fireEvent(TiC.EVENT_LONGCLICK, null);
return wasHandled;
});
}

Expand Down

0 comments on commit 5ac477c

Please sign in to comment.