I'm trying to add multiple gestures onto a view. I have successfully got them to work separately, but when I combine, only one ends up working, what am I doing incorrectly?
The first gesture I'm adding is a Scale Gesture
:
public class MyScaleGestures implements View.OnTouchListener, ScaleGestureDetector.OnScaleGestureListener {
private View view;
private ScaleGestureDetector gestureScale;
private float scaleFactor = 1;
private boolean inScale = false;
public MyScaleGestures (Context c){ gestureScale = new ScaleGestureDetector(c, this); }
@Override
public boolean onTouch(View view, MotionEvent event) {
this.view = view;
gestureScale.onTouchEvent(event);
return true;
}
@Override
public boolean onScale(ScaleGestureDetector detector) {
scaleFactor *= detector.getScaleFactor();
Log.d(TAG, "onScale: " + scaleFactor);
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
return true;
}
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
return true;
}
@Override
public void onScaleEnd(ScaleGestureDetector detector) { inScale = false; }
}
and my second Gesture is a SimpleOnGestureListener
:
private class FlingGestureDetector extends GestureDetector.SimpleOnGestureListener {
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
return true;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
return true;
}
}
Combining both into one class:
public class OnSwipeTouchListener implements View.OnTouchListener, ScaleGestureDetector.OnScaleGestureListener {
private final GestureDetector gestureDetector;
private ScaleGestureDetector gestureScale;
private OnSwipeTouchListener(Context context) {
gestureDetector = new GestureDetector(context, new FlingGestureDetector());
gestureScale = new ScaleGestureDetector(context, this);
}
public boolean onTouch(View v, MotionEvent event) {
gestureDetector.onTouchEvent(event);
gestureScale.onTouchEvent(event);
return true;
}
@Override
public boolean onScale(ScaleGestureDetector detector) {
Log.d(TAG, "onScale: " + detector.getScaleFactor());
return false;
}
and using it:
sceneView.setOnTouchListener(new OnSwipeTouchListener(this));
After combining them, only one the first gesture ends up working (gestureDetector)
. How can I get both to listen onto the view?
When combining them, the onScale
method is never called when performing the pinch
action in gestureScale
. But it works seperately when I don't include the other gesture.
You need to wrap all your gestures on one OnTouchListener
class and implement your logic.
In the below example, I missed all arguments. and you should provide all of them by your requirement.
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
class MyGesture implements View.OnTouchListener {
private View view;
private MyDetector myDetector;
private ScaleGestureDetector scaleDetector;
private GestureDetector gestureDetector;
public MyGesture(View view, MyDetector myDetector) {
this.view = view;
this.myDetector = myDetector;
initialGestures();
}
private void initialGestures() {
scaleDetector = new ScaleGestureDetector(
view.getContext(),
new ScaleGestureDetector.SimpleOnScaleGestureListener() {
@Override
public boolean onScale(ScaleGestureDetector detector) {
myDetector.onScale();
return true;
}
});
gestureDetector = new GestureDetector(
view.getContext(),
new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
myDetector.onFling();
return false;
}
});
}
@Override
public boolean onTouch(View v, MotionEvent event) {
gestureDetector.onTouchEvent(event);
scaleDetector.onTouchEvent(event);
return true;
}
interface MyDetector {
void onScale();
void onFling();
}
}
and use it:
myView.setOnTouchListener(new MyGesture(myView, new MyGesture.MyDetector() {
@Override
public void onScale() {
// do sth
}
@Override
public void onFling() {
// do sth
}
}));