Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vertical and Horizontal gestures in Android

I would like my GestureOverlayView to detect both purely horizontal as well as vertical gestures.

From http://android-developers.blogspot.com/2009/10/gestures-on-android-16.html

"orientation: indicates the scroll orientation of the views underneath. In this case the list scrolls vertically, which means that any horizontal gestures (like action_delete) can immediately be recognized as a gesture. Gestures that start with a vertical stroke must contain at least one horizontal component to be recognized. In other words, a simple vertical line cannot be recognized as a gesture since it would conflict with the list's scrolling."

Seems like a catch-22, if the android:orientation is set to vertical, I can only have horizontal swipes, and if the android:orientation is set to horizontal, I can only have vertical swipes. How can I get around this requirement?

like image 408
Bashevis Avatar asked Jun 30 '12 08:06

Bashevis


2 Answers

I had run into this problem at a hackathon. There's no way you can solve it with GestureOverlayView, so you have to use motion events. GestureOverlayView however works with slightly more "detailed" gestures, like a circle. What I've noticed is that GestureOverlayView best works for closed figures. So, motionEvent sensor it is. I found the code here. I modified Gav's answer for vertical swipes too. Haven't tested it though, but positive that it should work.

Here's an example:

public class SelectFilterActivity extends Activity implements OnClickListener
{

private static final int SWIPE_MIN_DISTANCE = 120;
private static final int SWIPE_MAX_OFF_PATH = 250;
private static final int SWIPE_THRESHOLD_VELOCITY = 200;
private GestureDetector gestureDetector;
View.OnTouchListener gestureListener;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    /* ... */

    // Gesture detection
    gestureDetector = new GestureDetector(new MyGestureDetector());
    gestureListener = new View.OnTouchListener() {
        public boolean onTouch(View v, MotionEvent event) {
            return gestureDetector.onTouchEvent(event);
        }
    };

}

class MyGestureDetector extends SimpleOnGestureListener {
    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        try {
            // downward swipe
            if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH && Math.abs(velocityY) > SWIPE_THRESHOLD_VELOCITY)
                Toast.makeText(SelectFilterActivity.this, "Downward Swipe", Toast.LENGTH_SHORT).show();
 else if (Math.abs(e2.getY() - e1.getY()) > SWIPE_MAX_OFF_PATH && Math.abs(velocityY) > SWIPE_THRESHOLD_VELOCITY)
                Toast.makeText(SelectFilterActivity.this, "Upward Swipe", Toast.LENGTH_SHORT).show();
            // right to left swipe
            else if(e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
                Toast.makeText(SelectFilterActivity.this, "Left Swipe", Toast.LENGTH_SHORT).show();
            }  else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
                Toast.makeText(SelectFilterActivity.this, "Right Swipe", Toast.LENGTH_SHORT).show();
            }
        } catch (Exception e) {
            // nothing
        }
        return false;
    }

}

Now add it to the views where you'd like gesture detection,

// Do this for each view added to the grid
    imageView.setOnClickListener(SelectFilterActivity.this); 
    imageView.setOnTouchListener(gestureListener);

Cheers to Gav for the code!

like image 180
Karthik Balakrishnan Avatar answered Sep 23 '22 03:09

Karthik Balakrishnan


All you have to do, is set the GestureStrokeAngleThreshold to a value closer to 90 (I used 90f)

The default value of the angle threashold is 40.0f because of which your simple vertical gestures would be skipped

like image 36
Sagar Sodah Avatar answered Sep 23 '22 03:09

Sagar Sodah