9

I want to be able to swipe anywhere on the screen to call a certain function. But I also have Buttons in Linear Layouts that I want to be able to click on. If I swipe on a Button I want onInterceptTouchEvent to Intercept the call to the Button's onTouchEvent and perform a swipe action. And if I simply click on a Button I do not want the onInterceptTouchEvent to be called. Rather, I want the Button's onTouchEvent to be called and perform a Button click

But I get errors when I try implementing onInterceptTouchEvent.

Here is my code:

public class Game extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.game_activity);

   //other code....
}
}

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            break;
        case MotionEvent.ACTION_CANCEL:
        case MotionEvent.ACTION_UP:
            swipeScreen(); //if action recognized as swipe then swipe
            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);

            if (yDelta > xDelta) {
                return true;
            }
            break;
    }

    return false;
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    ButtonOnClick(); //if not a swipe, then button click
    return true;
}

First the error says: The method onInterceptTouchEvent(MotionEvent) of type Game must override or implement a supertype method

Then instead of return true I change the code to:return super.onInterceptTouchEvent(event) but then I get an error saying: The method onInterceptTouchEvent(MotionEvent) is undefined for the type Activity

Can someone please help?

user2456977
  • 3,830
  • 14
  • 48
  • 87

2 Answers2

17

Note that onInterceptTouchEvent() is a method from the ViewGroup class, and not from Activity.

You can achieve the desired behavior by moving your logic from onInterceptTouchEvent() to dispatchTouchEvent(MotionEvent ev). Remember to call the superclass implementation of dispatchTouchEvent(MotionEvent ev) to handle the events that should be handled normally.

Also note that you should consider a movement to be a swipe only when the delta is bigger than the system constant for touch slop. And I suggest making sure that the user is swiping in the direction you want by testing yDelta / 2 > xDelta instead of yDelta > xDelta.

public class Game extends Activity {
    private int mSlop;
    private float mDownX;
    private float mDownY;
    private boolean mSwiping;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.game_activity);

        ViewConfiguration vc = ViewConfiguration.get(this)
        mSlop = vc.getScaledTouchSlop();

       //other code....
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mDownX = ev.getX();
                mDownY = ev.getY();
                mSwiping = false;
                break;
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                if(mSwiping) {
                    swipeScreen(); //if action recognized as swipe then swipe
                }
                break;
            case MotionEvent.ACTION_MOVE:
                float x = ev.getX();
                float y = ev.getY();
                float xDelta = Math.abs(x - mDownX);
                float yDelta = Math.abs(y - mDownY);

                if (yDelta > mSlop && yDelta / 2 > xDelta) {
                    mSwiping = true;
                    return true;
                }
                break;
        }

        return super.dispatchTouchEvent(ev);
    }
}
Fier
  • 342
  • 1
  • 4
  • 11
brnunes
  • 1,943
  • 26
  • 30
0

I use fernandohur approach (read his post), that is very reusable, self contained and gives everything needed to detect a swipe in any direction.

To use fernandohur onSwipeListener, follow these simple steps. All code is written in Kotlin:

// 1) Add his onSwipeListener to the project. Credits should go to him

// 2) Implement an anonymous class for the swipe listener:
val onSwipeListener: OnSwipeListener = object : OnSwipeListener() {
    override fun onSwipe(direction: Direction): Boolean {

        if (direction == Direction.Up) {
            //do somethin
            return true
        } else if (direction == Direction.Down) {
            //do something else
            return true
        }
        return super.onSwipe(direction)
    }
}

// 3) connect the listener to the view
val mDetector = GestureDetectorCompat(this.context, onSwipeListener)

// 4) route the touch events to the listener
override fun onInterceptTouchEvent(event: MotionEvent?): Boolean {
    return if (this.mDetector!!.onTouchEvent(event)) {
        true
    } else super.onInterceptTouchEvent(event)
}
MiguelSlv
  • 14,067
  • 15
  • 102
  • 169