Search code examples
androidgesture

Android multi finger gesture


I am working on multi finger gestures, I tried using Google gesture builder but it will not support for multi finger gestures, How to recognize two finger V shape gesture in android.?


Solution

  • I'm sure you can use a ScaleGestureDetector for this.

    After all a "V" from the top is just a pinch with some translation on the Y axis.

    So I think you can analyse the focus point and scale factor to determine a "V" has taken place.

    Here is a working example. In the end I didn't need to look at the scale. There are a couple of sensitivity values you can adjust such as the range of acceptable angles and the ratio of Y to X movement.

    import android.app.Activity;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.MotionEvent;
    import android.view.ScaleGestureDetector;
    import android.widget.TextView;
    
    public class MainActivity extends Activity {
    
        public static class VListener extends
                ScaleGestureDetector.SimpleOnScaleGestureListener {
            private float initialFocusX;
            private float initialFocusY;
    
            @Override
            public boolean onScaleBegin(ScaleGestureDetector detector) {
                Log.d(TAG, String.format("%.2f,%.2f s:%.2f", detector.getFocusX(),
                        detector.getFocusY(), detector.getScaleFactor()));
                initialFocusX = detector.getFocusX();
                initialFocusY = detector.getFocusY();
                return true;
            }
    
            @Override
            public void onScaleEnd(ScaleGestureDetector detector) {
                float deltaX = detector.getFocusX() - initialFocusX;
                float deltaY = detector.getFocusY() - initialFocusY;
    
                if (deltaY == 0) {
                    Log.d(TAG, "Not a V, no Y movement");
                    onNonV();
                    return;
                }
    
                float yMovementRatio = Math.abs(deltaY / deltaX);
                if (yMovementRatio < 4) {
                    Log.d(TAG,
                            String.format(
                                    "Not a V, the ratio of Y movement to X was not high enough: %.2f",
                                    yMovementRatio));
                    onNonV();
                    return;
                }
    
                float angle = (float) Math.toDegrees(Math.atan2(deltaY, deltaX));
                if (angle > 80 && angle < 100) {
                    Log.d(TAG, "V!");
                    onV();
                    return;
                } else {
                    Log.d(TAG,
                            String.format(
                                    "Not a V, the angle shows the V was drawn in the wrong direction: %.2f",
                                    angle));
                    onNonV();
                }
            }
    
            protected void onV() {
            }
    
            protected void onNonV() {
            }
        }
    
        protected static final String TAG = "MainActivity";
    
        private ScaleGestureDetector mScaleGestureDetector;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            final TextView t = (TextView) findViewById(R.id.vTextIndicator);
    
            mScaleGestureDetector = new ScaleGestureDetector(this, new VListener() {
                @Override
                protected void onV() {
                    t.setText("V!");
                }
    
                @Override
                protected void onNonV() {
                    t.setText("Non V");
                }
            });
        }
    
        public boolean onTouchEvent(MotionEvent event) {
            boolean retVal = mScaleGestureDetector.onTouchEvent(event);
            return retVal || super.onTouchEvent(event);
        }
    
    }
    

    activity_main.xml Layout is just:

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    
        <TextView
            android:id="@+id/vTextIndicator"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true" />
    
    </RelativeLayout>