androidandroid-gesture

Bezel Gestures with Android


I'm working on an application (on a Galaxy Nexus), and I noticed that Google implemented the "Google Now" application when you swipe from the bottom of the bezel onto the screen (the chrome browser also did this for a while, not sure if it still does). I've been looking around but have been unable to determine how they accomplished this. Is there an easy way to handle gestures that begin in the bezel rather than on the screen?

I checked the developer pages for reference, but the only article I could find was here:

http://developer.android.com/design/patterns/gestures.html

Is there anywhere else where this information would be available?

[Edit]

I've been trying very unsuccessfully to get edge gestures working based on Lain_B's method, but cannot make it work. Here's the code that I'm using to try and detect the gestures, but logcat is always outputting a zero...

public class MainActivity extends Activity implements OnGestureListener {

private GestureDetector myGesture;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    myGesture = new GestureDetector(getBaseContext(),
            (OnGestureListener) this);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.activity_main, menu);
    return true;
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    Log.e("Flags Touch", "Flags: " + event.getEdgeFlags());
    return myGesture.onTouchEvent(event);
}

@Override
public boolean onDown(MotionEvent e) {
    Log.e("Flags", "Flags: " + e.getEdgeFlags());
    Log.e("Event", "onDown");
    // TODO Auto-generated method stub
    return false;
}

@Override
public void onLongPress(MotionEvent e) {
    Log.e("Event", "onLongPress");
    // TODO Auto-generated method stub

}

@Override
public void onShowPress(MotionEvent e) {
    Log.e("Flags", "Flags: " + e.getEdgeFlags());
    Log.e("Event", "onShowPress");
    // TODO Auto-generated method stub

}

@Override
public boolean onSingleTapUp(MotionEvent e) {
    Log.e("Event", "onSingleTapUp");
    // TODO Auto-generated method stub
    return false;
}

@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
        float distanceY) {
    // Log.e("Event", "onScroll");
    return false;
}

// these constants are used for onFling
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;

@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
        float velocityY) {

    Log.e("Event", "onFling");
    Log.e("Flags", "Flags: " + e1.getEdgeFlags());

    if (e1.getEdgeFlags() == MotionEvent.EDGE_LEFT) {
        // code to handle swipe from left edge
        Log.e("!!!!!", "Edge fling!");
    }

    try {
        // do not do anything if the swipe does not reach a certain length
        // of distance
        if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH)
            return false;

        // right to left swipe
        if (e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE
                && Math.abs(velocityX) < SWIPE_THRESHOLD_VELOCITY) {

        }
        // left to right swipe
        else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE
                && Math.abs(velocityX) < SWIPE_THRESHOLD_VELOCITY) {

        }
    } catch (Exception e) {
        // nothing
    }
    return false;

}
}

[Edit 2]

With Lain_B's requested output...

(Using Nexus 7)... Starting from farthest possible left point on the bezel, and swiping right to the middle(ish).

08-16 16:44:13.674: I/Fling(16702): Flags: 0
08-16 16:44:13.674: I/Fling(16702): e1: 2.5 711.5152
08-16 16:44:13.674: I/Fling(16702): e2: 215.4591 717.08105

Swiping from the center point of the screen, off the screen (to the right side)

08-16 16:46:37.364: I/Fling(16702): Flags: 0
08-16 16:46:37.364: I/Fling(16702): e1: 392.5 758.1818
08-16 16:46:37.364: I/Fling(16702): e2: 783.4375 743.3334

Solution

  • I think MotionEvent.getEdgeFlags() is what you're looking for. You can then compare the returned value with EDGE_LEFT , EDGE_RIGHT , etc to see which edge was touched.

    if( event1.getEdgeFlags()&MotionEvent.EDGE_LEFT != 0 ){
        //code to handle swipe from left edge
    }
    

    or

    if( e1.getX() < 5.0f ){
        //handle swipe from left edge
    }