How to use GestureDetector?

7

I would like a practical example for this method, as I want it to detect motion to the left executes a command and if it is to the right executes another command.

Searching the net found this code seems to be working, however it does not sense movement by having several buttons if someone knows how to fix this problem. Link where I found the code

public class MinhaActivity extends Activity implements OnGestureListener {

    private GestureDetector detector = null;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);    
        this.detector = new GestureDetector(this);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if(this.detector.onTouchEvent(event)) {
             return true;
        }
         return super.onTouchEvent(event);
    }

    @Override
    public boolean onDown(MotionEvent arg0) {
         return false;
    }

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

        if (Math.abs(e1.getY() - e2.getY()) > 250) {
            return false;
        }
        // Movimento da direita para esquerda
        if(e1.getX() - e2.getX() > 100 && Math.abs(velocityX) > 200) {
            //Faz algo aqui....
        } else if (e2.getX() - e1.getX() > 100 && Math.abs(velocityX) > 200) {
            //Faz algo aqui....         
        }

    return true;
    }

    @Override
    public void onLongPress(MotionEvent event) { }

    @Override
    public boolean onScroll(MotionEvent arg0, MotionEvent arg1, float arg2, float arg3) {
         return false;
    }

    @Override
    public void onShowPress(MotionEvent arg0) { }

    @Override
    public boolean onSingleTapUp(MotionEvent arg0) {
         return false;
    }

}
    
asked by anonymous 14.05.2015 / 19:51

3 answers

3

In order to detect the swipe movement over the buttons or any other view , without having to implement this logic in each / em>, we must find a way to intercept this movement before them.

The ViewGroup class has the onInterceptTouchEvent () which, when implemented, allows you to intercept the MotionEvent that are sent to views daughters. If the method returns true , MotionEvent will be passed to the onTouchEvent() method of ViewGroup , otherwise, it is passed to onTouchEvent() of view where the event occurred.

We will then have to write a class that inherits from a ViewGroup (in the FrameLayout case) and implement the methods onInterceptTouchEvent() and onTouchEvent() to treat motion of Swipe .

public class SwipeInterceptor extends FrameLayout {

    public interface OnSwipeListener{
        public void onSwipeLeft();
        public void onSwipeRight();
    }

    private OnSwipeListener mSwipeListener;
    private int mTouchSlop;
    private boolean mIsDragged;
    private float mLastX;
    private float mLastY;
    private float mStartX;
    private float mDeltaXTotal = 0;

    public SwipeInterceptor(Context context, AttributeSet attrs) {
        super(context, attrs);
        setTouchSlop(context);
    }

    //Api level 21 ou superior
/*  public SwipeInterceptor(Context context, AttributeSet attrs,
            int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        setTouchSlop(context);
    }*/

    public SwipeInterceptor(Context context, AttributeSet attrs,
            int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        setTouchSlop(context);
    }

    public SwipeInterceptor(Context context) {
        super(context);
        setTouchSlop(context);
    }

    public void setOnSwipeListenner(OnSwipeListener listener) {
        mSwipeListener = listener;
    }
    private void setTouchSlop(Context context){
        ViewConfiguration vc = ViewConfiguration.get(context);
        mTouchSlop = vc.getScaledTouchSlop();
    }
    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mLastX = event.getX();
                mLastY = event.getY();
                mStartX = mLastX;
                break;
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                mIsDragged = false;
                break;
            case MotionEvent.ACTION_MOVE:
                float x = event.getX();
                float y = event.getY();
                float xDelta = Math.abs(x - mLastX);
                float yDelta = Math.abs(y - mLastY);

                float xDeltaTotal = x - mStartX;
                if (xDelta > yDelta && Math.abs(xDeltaTotal) > mTouchSlop) {
                    mIsDragged = true;
                    mStartX = x;
                    return true;
                }
                break;
        }

        return false;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                if (mIsDragged && mSwipeListener != null) {
                    if(mDeltaXTotal > 0)
                        mSwipeListener.onSwipeRight();
                    else mSwipeListener.onSwipeLeft();
                }
                mIsDragged = false;
                mDeltaXTotal = 0;
                break;
            case MotionEvent.ACTION_MOVE:
                float x = event.getX();
                float y = event.getY();

                float xDelta = Math.abs(x - mLastX);
                float yDelta = Math.abs(y - mLastY);

                 mDeltaXTotal = x - mStartX;
                if (!mIsDragged && xDelta > yDelta && Math.abs(mDeltaXTotal) > mTouchSlop) {
                    mIsDragged = true;
                    mStartX = x;
                    mDeltaXTotal = 0;
                }
                mLastX = x;
                mLastY = y;
                break;
        }

        return true;
    }
}

As you can see, the onInterceptTouchEvent() method only returns true in the case of MotionEvent.ACTION_MOVE , because that's just the movement we want to intercept.

The whole code comes down to some math to see if the move made should be considered as a Swipe and what its direction is.

The class declares the OnSwipeListener interface with the onSwipeLeft() and onSwipeRight() methods that will be called when those motions are detected. The class that implements them must be registered using the setOnSwipeListenner() method.

Implementation

The implementation goes through, first putting your layout into our FrameLayout

<nome_da_sua_package.SwipeInterceptor 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:id="@+id/swipe">

        <!-- coloque aqui o seu layout -->

</nome_da_sua_package.SwipeInterceptor>

and then implement the OnSwipeListener interface. One of the possible ways is to make your Activity implement it:

public class MainActivity extends Activity implements OnSwipeListener{

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

        //Obtém a referência ao SwipeInterceptor.
        SwipeInterceptor swipe = (SwipeInterceptor)findViewById(R.id.swipe);
        //Registra a nossa Activity para receber os eventos onSwipeLeft e onSwipeRight
        swipe.setOnSwipeListenner(this);
    }

    // Declaração dos métodos da interface OnSwipeListener
    @Override
    public void onSwipeLeft() {

        Toast.makeText(MainActivity.this, "Swipe Left", Toast.LENGTH_SHORT).show();

    }

    @Override
    public void onSwipeRight() {

        Toast.makeText(MainActivity.this, "Swipe Right", Toast.LENGTH_SHORT).show();
    }

}

Inspiration: Documentation for Android and this article .

    
26.05.2015 / 11:42
1

Try this (refactory): add the attribute:

private GestureDetector gesto;

then in onCreate use this code:

CustomGestureDetector customGestureDetector = new CustomGestureDetector()
gesto = new GestureDetector(this, customGestureDetector);
View v = new RelativeLayout(this);
v.setOnTouchListener(new OnTouchListener() {
   @Override
   public boolean onTouch(View v, final MotionEvent event) {
      gesto.onTouchEvent(event);
      return true;
   }
});

Let's try using method. Add this method:

@Override
public boolean onTouchEvent(MotionEvent event) {
    gesto.onTouchEvent(event);

    return super.onTouchEvent(event);
}

and this:

@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        if (e1.getX() < e2.getX()) {
           Log.d(TAG, "Left to Right swipe performed");
        }

        if (e1.getX() > e2.getX()) {
           Log.d(TAG, "Right to Left swipe performed");
        }

        if (e1.getY() < e2.getY()) {
           Log.d(TAG, "Up to Down swipe performed");
        }

        if (e1.getY() > e2.getY()) {
           Log.d(TAG, "Down to Up swipe performed");
        }

        return true;
 }
    
14.05.2015 / 21:06
0

Good night, good friend! Have a look if this works for you:

GestureListener.java

class GestureListener extends GestureDetector.SimpleOnGestureListener
{

       static String currentGestureDetected;

      @Override
      public boolean onSingleTapUp(MotionEvent ev) {
          currentGestureDetected=ev.toString();

        return true;
      }
      @Override
      public void onShowPress(MotionEvent ev) {
          currentGestureDetected=ev.toString();

      }
      @Override
      public void onLongPress(MotionEvent ev) {
          currentGestureDetected=ev.toString();

      }
      @Override
      public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
          currentGestureDetected=e1.toString()+ "  "+e2.toString();

        return true;


}
  @Override
  public boolean onDown(MotionEvent ev) {
      currentGestureDetected=ev.toString();

    return true;
  }
  @Override
  public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
      currentGestureDetected=e1.toString()+ "  "+e2.toString();
    return true;
  }
}

MainActivity.java

public class MainActivity extends Activity
{

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

        // vincula o gestureDetector ao GestureListener
        mGestureDetector = new GestureDetector(this, new GestureListener());
    }

    //sempre que você tocar na tela o método onTouch() é chamado
    @Override
    public boolean onTouchEvent(MotionEvent event)
    {
        //o método onTouchEvent analisa que tipo de toque foi (arrastando, etc)
        boolean eventConsumed=mGestureDetector.onTouchEvent(event);
        if (eventConsumed)
        {
            Toast.makeText(this,GestureListener.currentGestureDetected,Toast.LENGTH_LONG).show();
            return true;
        }
        else
            return false;
    }
}

The source of this code can be found here . If you still have questions or can not make it work, please let me know!

    
17.05.2015 / 01:19