Skip to content

Commit

Permalink
fix: android fixes for native gestures
Browse files Browse the repository at this point in the history
  • Loading branch information
farfromrefug committed Nov 15, 2020
1 parent 3b2d2ec commit c6321bb
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@
import android.view.KeyEvent;
import android.util.AttributeSet;
import android.view.inputmethod.InputMethodManager;
import android.util.Log;

import com.swmansion.gesturehandler.GestureHandler;

import java.util.HashMap;

public class GestureHandlerInteractionController
implements com.swmansion.gesturehandler.GestureHandlerInteractionController {
public class GestureHandlerInteractionController implements com.swmansion.gesturehandler.GestureHandlerInteractionController {
private HashMap<Number, int[]> mWaitForRelations = new HashMap();
private HashMap<Number, int[]> mSimultaneousRelations = new HashMap();

Expand Down Expand Up @@ -59,6 +59,9 @@ public boolean shouldHandlerBeCancelledBy(GestureHandler handler, GestureHandler

public boolean shouldRecognizeSimultaneously(GestureHandler handler, GestureHandler otherHandler) {
int[] simultHandlerTags = mSimultaneousRelations.get(handler.getTag());
if (GestureHandler.debug) {
Log.d("JS", "GestureHandlerInteractionController shouldRecognizeSimultaneously " + handler + " " + otherHandler + " " + simultHandlerTags);
}
if (simultHandlerTags != null) {
for (int i = 0; i < simultHandlerTags.length; i++) {
if (simultHandlerTags[i] == otherHandler.getTag()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.util.Log;

import org.nativescript.widgets.ItemSpec;
import org.nativescript.widgets.GridUnitType;

import com.swmansion.gesturehandler.GestureHandlerOrchestrator;
import com.swmansion.gesturehandler.GestureHandlerRegistryImpl;
import com.swmansion.gesturehandler.PointerEventsConfig;
import com.swmansion.gesturehandler.GestureHandler;
import com.swmansion.gesturehandler.ViewConfigurationHelper;

public class PageLayout extends org.nativescript.widgets.GridLayout {
Expand All @@ -30,6 +32,9 @@ public PageLayout(Context context) {
private boolean mPassingTouch = false;

public void setShouldIntercept(boolean value) {
if (GestureHandler.debug) {
Log.d("JS", "PageLayout setShouldIntercept " + value);
}
this.mShouldIntercept = value;
}

Expand All @@ -55,6 +60,9 @@ public GestureHandlerRegistryImpl registry() {
// return super.dispatchTouchEvent(ev);
// }
public void tryCancelAllHandlers() {
if (GestureHandler.debug) {
Log.d("JS", "PageLayout tryCancelAllHandlers ");
}
// In order to cancel handlers we activate handler that is hooked to the root view
if (this.rootGestureHandler != null && this.rootGestureHandler.getState() == com.swmansion.gesturehandler.GestureHandler.STATE_BEGAN) {
// Try activate main JS handler
Expand All @@ -64,6 +72,9 @@ public void tryCancelAllHandlers() {
}

public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
if (GestureHandler.debug) {
Log.d("JS", "PageLayout requestDisallowInterceptTouchEvent " + disallowIntercept + " " + this.mPassingTouch);
}
// If this method gets called it means that some native view is attempting to grab lock for
// touch event delivery. In that case we cancel all gesture recognizers
if (this.mOrchestrator != null && !this.mPassingTouch) {
Expand All @@ -78,7 +89,9 @@ public boolean dispatchTouchEventToOrchestrator(MotionEvent ev) {
this.mPassingTouch = true;
this.mOrchestrator.onTouchEvent(ev);
this.mPassingTouch = false;

// if (GestureHandler.debug) {
// Log.d("JS", "PageLayout dispatchTouchEventToOrchestrator " + this.mShouldIntercept);
// }
return this.mShouldIntercept;
}

Expand Down Expand Up @@ -106,7 +119,7 @@ public boolean dispatchTouchEvent(MotionEvent ev) {
* handler library logic. Unless this method is called (which happens as a result of instantiating
* new gesture handler from JS) the root view component will just proxy all touch related methods
* to its superclass. Thus in the "disabled" state all touch related events will fallback to
* default RN behavior.
* default behavior.
*/
public void initialize() {
this.mRegistry = new com.swmansion.gesturehandler.GestureHandlerRegistryImpl();
Expand All @@ -124,22 +137,17 @@ public View getChildInDrawingOrderAtIndex(ViewGroup parent, int index) {
}
};
this.mOrchestrator = new com.swmansion.gesturehandler.GestureHandlerOrchestrator(this, this.mRegistry, this.configurationHelper);
// console.log(this.constructor.name, 'initialize', this.mOrchestrator, this.mRegistry);
this.mOrchestrator.setMinimumAlphaForTraversal(0.01f);

this.rootGestureHandler = new RootViewGestureHandler();
this.rootGestureHandler.setTag(GESTURE_HANDLER_TAG);
this.mRegistry.registerHandler(this.rootGestureHandler);
// registry.attachHandlerToView(this.rootGestureHandler.getTag(), this);
this.mRegistry.attachHandlerToView(GESTURE_HANDLER_TAG, this);
}

public void tearDown() {
this.configurationHelper = null;
this.mOrchestrator = null;
this.mRegistry = null;
// if (this.mGestureRootHelper != null) {
// this.mGestureRootHelper.tearDown();
// this.mGestureRootHelper = null;
// }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
import com.swmansion.gesturehandler.GestureHandler;
import android.os.SystemClock;
import android.view.View;

import android.util.Log;

public class RootViewGestureHandler extends GestureHandler {
private static final String TAG = "RootViewGestureHandler";
public RootViewGestureHandler() {
super();
}
Expand All @@ -19,17 +20,24 @@ protected void onHandle(MotionEvent event) {
final int currentState = getState();
if (currentState == GestureHandler.STATE_UNDETERMINED) {
begin();
getView().setShouldIntercept(true);
getView().setShouldIntercept(false);
}
if (event.getActionMasked() == MotionEvent.ACTION_UP) {
end();
}
}

protected void onCancel() {
getView().setShouldIntercept(false);
if (GestureHandler.debug) {
Log.d("JS", "RootViewGestureHandler onCancel");
}
getView().setShouldIntercept(true);
final long time = SystemClock.uptimeMillis();
final MotionEvent event = MotionEvent.obtain(time, time, MotionEvent.ACTION_CANCEL, 0, 0, 0);
event.setAction(MotionEvent.ACTION_CANCEL);
getView().onTouchEvent(event);
}
// public boolean shouldRecognizeSimultaneously(GestureHandler handler) {
// return true;
// }
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

import android.os.Handler;
import android.view.MotionEvent;
import android.util.Log;

public class FlingGestureHandler extends GestureHandler<FlingGestureHandler> {
private static final String TAG = "FlingGestureHandler";
private static final long DEFAULT_MAX_DURATION_MS = 800;
private static final long DEFAULT_MIN_ACCEPTABLE_DELTA = 160;
private static final int DEFAULT_DIRECTION = DIRECTION_RIGHT | DIRECTION_LEFT | DIRECTION_UP | DIRECTION_DOWN;
Expand Down Expand Up @@ -74,6 +76,9 @@ private boolean tryEndFling(MotionEvent event) {
}

private void endFling(MotionEvent event) {
if (GestureHandler.debug) {
Log.d("JS", "FlingGestureHandler endFling");
}
if (!tryEndFling(event)) {
fail();
}
Expand Down Expand Up @@ -103,6 +108,9 @@ protected void onHandle(MotionEvent event) {

@Override
protected void onCancel() {
if (GestureHandler.debug) {
Log.d("JS", "FlingGestureHandler onCancel");
}
if (mHandler != null) {
mHandler.removeCallbacksAndMessages(null);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

public class GestureHandler<T extends GestureHandler> {
private final String TAG = "GestureHandler";
public static boolean debug = false;

public static final int STATE_UNDETERMINED = 0;
public static final int STATE_FAILED = 1;
Expand Down Expand Up @@ -452,6 +453,9 @@ public final void cancel() {
}

public final void fail() {
if (GestureHandler.debug) {
Log.d("JS", "GestureHandler fail " + this);
}
if (mState == STATE_ACTIVE || mState == STATE_UNDETERMINED || mState == STATE_BEGAN) {
moveToState(STATE_FAILED);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,11 @@ private void cleanupAwaitingHandlers() {

void onHandlerStateChange(GestureHandler handler, int newState, int prevState) {
mHandlingChangeSemaphore += 1;
if (GestureHandler.debug) {
Log.d("JS", "GestureHandlerOrchestrator onHandlerStateChange " + handler + " " + prevState + " " + newState);
}
if (isFinished(newState)) {

// if there were handlers awaiting completion of this handler, we can trigger
// active state
for (int i = 0; i < mAwaitingHandlersCount; i++) {
Expand Down Expand Up @@ -212,13 +216,6 @@ private void makeActive(GestureHandler handler) {
handler.mIsActive = true;
handler.mActivationIndex = mActivationIndex++;

// TODO: for now we do it the same as android and disable
// native gestures once a gesture is recognized
long time = SystemClock.uptimeMillis();
MotionEvent event = MotionEvent.obtain(time, time, MotionEvent.ACTION_CANCEL, 0, 0, 0);
event.setAction(MotionEvent.ACTION_CANCEL);
handler.getView().dispatchTouchEvent(event);

int toCancelCount = 0;
// Cancel all handlers that are required to be cancel upon current handler's
// activation
Expand Down Expand Up @@ -541,6 +538,9 @@ private static boolean canRunSimultaneously(GestureHandler a, GestureHandler b)

private static boolean shouldHandlerBeCancelledBy(GestureHandler handler, GestureHandler other) {

if (GestureHandler.debug) {
Log.d("JS", "GestureHandlerOrchestrator shouldHandlerBeCancelledBy " + handler + " " + other + " " + handler.hasCommonPointers(other) + " " + canRunSimultaneously(handler, other) + " " + handler.shouldBeCancelledBy(other));
}
if (!handler.hasCommonPointers(other)) {
// if two handlers share no common pointer one can never trigger cancel for the
// other
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ public boolean shouldRecognizeSimultaneously(GestureHandler handler) {
}

boolean canBeInterrupted = !mDisallowInterruption;

if (GestureHandler.debug) {
Log.d("JS", "NativeViewGestureHandler shouldRecognizeSimultaneously " + canBeInterrupted);
}
int state = getState();
int otherState = handler.getState();

Expand All @@ -73,47 +77,65 @@ public boolean shouldRecognizeSimultaneously(GestureHandler handler) {

@Override
public boolean shouldBeCancelledBy(GestureHandler handler) {

// if (GestureHandler.debug) {
// Log.d("JS", "NativeViewGestureHandler shouldBeCancelledBy " + mDisallowInterruption);
// }
return !mDisallowInterruption;
}

@Override
protected void onHandle(MotionEvent event) {
View view = getView();
int state = getState();
if (GestureHandler.debug) {
Log.d("JS", "NativeViewGestureHandler onHandle " + state + " " + view +" " + event.getActionMasked() + " " + " " + mShouldActivateOnStart);
}
if (event.getActionMasked() == MotionEvent.ACTION_UP) {
view.onTouchEvent(event);
view.dispatchTouchEvent(event);
if ((state == STATE_UNDETERMINED || state == STATE_BEGAN) && view.isPressed()) {
activate();
}
end();
} else if (state == STATE_UNDETERMINED || state == STATE_BEGAN) {

if (mShouldActivateOnStart) {
tryIntercept(view, event);
view.onTouchEvent(event);
view.dispatchTouchEvent(event);
activate();
} else if (tryIntercept(view, event)) {
view.onTouchEvent(event);
view.dispatchTouchEvent(event);
activate();
} else if (state != STATE_BEGAN) {
begin();
}
} else if (state == STATE_ACTIVE) {
view.onTouchEvent(event);
view.dispatchTouchEvent(event);
}
}

private static boolean tryIntercept(View view, MotionEvent event) {
if (view instanceof ViewGroup && ((ViewGroup) view).onInterceptTouchEvent(event)) {
// if (GestureHandler.debug) {
// Log.d("JS", "NativeViewGestureHandler tryIntercept true");
// }
return true;
}
// if (GestureHandler.debug) {
// Log.d("JS", "NativeViewGestureHandler tryIntercept false");
// }
return false;
}

@Override
protected void onCancel() {

if (GestureHandler.debug) {
Log.d("JS", "NativeViewGestureHandler onCancel " + getView());
}
long time = SystemClock.uptimeMillis();
MotionEvent event = MotionEvent.obtain(time, time, MotionEvent.ACTION_CANCEL, 0, 0, 0);
event.setAction(MotionEvent.ACTION_CANCEL);
getView().dispatchTouchEvent(event);
getView().onTouchEvent(event);
}
}

0 comments on commit c6321bb

Please sign in to comment.