How to use Gesturedetector?

Asked

Viewed 1,117 times

7

I would like a practical example for this method, because I want you to detect left motion run a command and if you go right run another command.

Searching the net I found this code seems to be working, but it does not detect movement because it has 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;
    }

}

3 answers

2


To detect the movement of Swipe above the buttons or any other view, without having to implement this logic in each of the views, we need to find a way to intercept that movement before they.

The class Viewgroup has the method onInterceptTouchEvent() which, when implemented, makes it possible to intercept Motionevent which are sent to views daughters.
If the method returns true, the Motionevent will be passed to the method onTouchEvent() of Viewgroup, otherwise, is passed to onTouchEvent() of view where the event took place.

We will then have to write a class that inherits from a Viewgroup(in the case Framelayout) and implement the methods onInterceptTouchEvent() and onTouchEvent() in order to treat the movement 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;
    }
}

How to verify the method onInterceptTouchEvent() only returns true in the case of MotionEvent.ACTION_MOVE, because that’s all the movement we want to intercept.

The whole code comes down to some mathematics to know if the movement made should be considered as a Swipe and its direction.

Class declares the interface OnSwipeListener with the methods onSwipeLeft() and onSwipeRight() that will be called when these movements are detected.
The class that implements them must be registered through the method setOnSwipeListenner().

Implementation

The implementation goes through, first put your layout within 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 interface OnSwipeListener.
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();
    }

}

Source of inspiration: Documentation of Android and this article.

  • I have a question this method is for which version of Android

  • I think it works in any version.

  • to think it works on API 11 and higher, needed to test on this API, to using genymotion but has this API.

  • I don’t understand your doubt.

  • is that I needed this version of android to test, using genymotion that a great emulator to test the applications, so I asked a question about it but no one answered yet http://answall.com/questions/69598/como-installr-api-11-do-android-no-genymotion

  • If the genymotion there’s nothing to do.

  • Regarding your answer how to use to keep changing layout example I have 3 layout while making the move to right it will change layout, time that end it repeats so the same to left

  • Best to use one Viewpager

Show 3 more comments

1

Try this (refactory): add the attribute:

private GestureDetector gesto;

later on 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 it using method. Add this method:

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

    return super.onTouchEvent(event);
}

and that:

@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;
 }
  • v.setOnGestureListener(new OnGestureListener(){ this presented error on this line will be that nothing is missing in the code?

  • I made an edition in the code. da a look if now funf.

  • not yet, this presenting problem customGestureDetector error -->customGestureDetector cannot be resolved to a variable and here public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) error -->The method onFling(MotionEvent, MotionEvent, float, float) of type CalculadoraActivity must override or implement a supertype method

  • Sorry beast missed that part: Customgesturedetector customGestureDetector = new Customgesturedetector(); already edited the code from the other look.

  • Still not working, but still worth

0

Good night, good friend! Take a look if it 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 cannot make it work, please let me know!

  • 1

    I have a slight impression of having tried, well more I will try again this code as soon as I arrange the eclipse, I would like to point out that I would like to know how to make the Gesturedetector work on top of the buttons.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.