Tuesday, 6 October 2015

Gesture Detection in Android Part-1

What is a Gesture?


When you click a button or scroll a list, you basically perform some kind of gesture which is detected by the system as an event and system perform some action on that. Gestures allow users to interact with your app by manipulating the screen objects you provide.


Some common kind of gestures are:


1. Single click
2. Double click
3. Scroll
4. Long pressed
5. Zoom


What do android provide for Gesture Detection ?


Android framework provides a set of APIs which can be used to detect these kind of gestures in your application. All these gesture are performed by using action involving one or two fingers. GestuteDetector is the primary class which is used to detect the gestures. This class has two inner interface namely  OnDoubleTapListener for duble click gesture and OnGestureListener for gesture notification. This class has also an inner class SimpleOnGestureListener which is generally extended when you require only to detect a subset of gestures not all.


How to use GestureDetection API ?


1. First you need one of the below which will be used as argument for GestureDetection constructor.


  • Create a class which implements either OnDoubleTapListener or OnGestureListener.
  • Create a class which extends SimpleOnGestureListener.


2. Create an instance of GestureDetection for a view.  
 
3. Set the setOnTouchListener to the view and inside the OnTouch method of OnTouchListener, call onTouchEvent on the instance of GestureDetection.


Create a SimpleOnGestureListener class


A convenience class to extend when you only want to listen for a subset of all the gestures. This implements all methods in the GestureDetector.OnGestureListener and GestureDetector.OnDoubleTapListener but does nothing and return false for all applicable methods.This can be an inner class for the activity class or an independent class.


class MyGestureDetection extends GestureDetector.SimpleOnGestureListener{

@Override
public boolean onDown(MotionEvent e) {
// It must return true for any gesture to be detected.
return true;
}

@Override
public boolean onDoubleTap(MotionEvent e) {
// TODO Auto-generated method stub
return super.onDoubleTap(e);
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
return false;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
return false;
}
@Override
public void onLongPress(MotionEvent e) {
return;
}

           // four more methods are here….you can check documentation for that.
}


Whichever the methods you don’t need return false for them. Suppose you need fling and not scroll then return false for scroll.


Create an instance of GestureDetection for a view.  


public class MainActivity extends Activity {

private GestureDetector mDetector;

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

mDetector = new GestureDetector(this, new GestureDetection());
}
}


Set the setOnTouchListener to the view


public class MainActivity extends Activity {

private ImageView imageView;
private GestureDetector mDetector;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

imageView = (ImageView) findViewById(R.id.imageView1);
mDetector = new GestureDetector(this, new GestureDetection());

imageView.setOnTouchListener(new View.OnTouchListener() {

@Override
public boolean onTouch(View v, MotionEvent event) {
mDetector.onTouchEvent(event);
return true;
}
});

}


This detector instance can be applied to any view and viewgroup. If you want to apply it on the whole display area of activity instead of a view, then override onTouchEvent of activity class. Inside this method, call onTouchEvent method on detector instance instead of a view.


Apply for the whole view area


public class MainActivity extends Activity {

private ImageView imageView;
private GestureDetector mDetector;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDetector = new GestureDetector(this, new GestureDetection());
}

           @Override
public boolean onTouchEvent(MotionEvent event) {
mDetector.onTouchEvent(event);
return true;
}

}


In the next post, will will go through a demo application…..;)

Gesture Detection in Android Part-2

In the previous post, I have explained briefly how to use the Gesture Detection in api in android. If you want to  have a look, then please go the this link.


In this post, we will run a live example. In this example, there is an imageview inside the main layout. when you scroll fast or fling the imageview, image will changed whenever speed of scroll exceeds the value mentioned inside the application.


fling.png
MainActivity.java

package test.example.gestureflingactivity;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;

@SuppressLint("ClickableViewAccessibility")
public class MainActivity extends Activity {

private ImageView imageView;
private GestureDetector mDetector;
int imgId=0;

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

imageView = (ImageView) findViewById(R.id.imageView1);
imageView.setImageResource(R.drawable.mic_red);
mDetector = new GestureDetector(this, new GestureDetection());
imageView.setOnTouchListener(new View.OnTouchListener() {

@Override
public boolean onTouch(View v, MotionEvent event) {
mDetector.onTouchEvent(event);
return true;
}
});

}

class GestureDetection extends GestureDetector.SimpleOnGestureListener {

@Override
public boolean onDown(MotionEvent event) {
// Log.d(TAG, "onDown: " + event.toString());
// it must be return true to get any gesture.
return true;
}

@Override
public boolean onFling(MotionEvent event1, MotionEvent event2,
float velocityX, float velocityY) {

if (velocityX > 200) {

if(imgId==0){
imageView.setImageResource(R.drawable.micro_black);
imgId=1;
}else{
imageView.setImageResource(R.drawable.mic_red);
imgId=0;
}
}
return false;
}

}
}


activity_main


<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"
   android:paddingBottom="@dimen/activity_vertical_margin"
   android:paddingLeft="@dimen/activity_horizontal_margin"
   android:paddingRight="@dimen/activity_horizontal_margin"
   android:paddingTop="@dimen/activity_vertical_margin"
   tools:context="test.example.gestureflingactivity.MainActivity" >

   <TextView
       android:id="@+id/textView1"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="Fling Gesture Test"
       android:textSize="20sp"
       android:textStyle="bold"
       android:typeface="serif" />

   <ImageView
       android:id="@+id/imageView1"
       android:layout_width="200dp"
       android:layout_height="200dp"
       android:layout_below="@+id/textView1"
       android:layout_centerHorizontal="true"
       android:layout_marginTop="75dp"
       android:src="@drawable/ic_launcher" />

   <TextView
       android:id="@+id/textView2"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_alignLeft="@+id/imageView1"
       android:layout_alignParentBottom="true"
       android:layout_marginBottom="15dp"
       android:layout_marginLeft="18dp"
       android:text="Fast Scroll The Image"
       android:textAppearance="?android:attr/textAppearanceSmall" />

</RelativeLayout>