Method onTouchEvent not being called

2019-02-01 23:34发布

问题:

I'm having a problem that my method

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

is newer called. Any ideas why is that so? I'm building a google's api 4.0.3 application, and i'm trzing to enable swipes for my viewFliper. However it can't work if on touch is newer called.

btw:

 public class MainActivity extends SherlockMapActivity implements ActionBar.TabListener {

Thats the declaration of my activity. and to detect swipes i have implemented that:

    SimpleOnGestureListener simpleOnGestureListener = new SimpleOnGestureListener(){

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

        float sensitvity = 50;
        if((e1.getX() - e2.getX()) > sensitvity){
            SwipeLeft();
        }else if((e2.getX() - e1.getX()) > sensitvity){
            SwipeRight();
        }

        return true;
    }

};
GestureDetector gestureDetector= new GestureDetector(simpleOnGestureListener);

Thank u!

edit:

main.xml:

 <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/main_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >

<ViewFlipper
    android:id="@+id/ViewFlipper"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:background="#ffffff" >

    <include
        android:layout_height="match_parent"
        layout="@layout/mymain" />

    <include layout="@layout/secondmain" />
    <include layout="@layout/thirdmain" />
    <include layout="@layout/fourthmain" />
</ViewFlipper>
</LinearLayout>

edit2: all of my included layouts have scrollview implemented is it possible that scroll takes that events and handle them. And how to detect gestures if so?

回答1:

I found a perfect solution. I implemented new method:

@Override
public boolean dispatchTouchEvent(MotionEvent event) {

    View v = getCurrentFocus();
    boolean ret = super.dispatchTouchEvent(event);

and now it all works fine!

Edit:

My final code:

@Override
public boolean dispatchTouchEvent(MotionEvent event) {
    View v = getCurrentFocus();
    if (v instanceof EditText) {
        View w = getCurrentFocus();
        int scrcoords[] = new int[2];
        w.getLocationOnScreen(scrcoords);
        float x = event.getRawX() + w.getLeft() - scrcoords[0];
        float y = event.getRawY() + w.getTop() - scrcoords[1];
        if (event.getAction() == MotionEvent.ACTION_UP
                && (x < w.getLeft() || x >= w.getRight() || y < w.getTop() || y > w
                        .getBottom())) {

            InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
            imm.hideSoftInputFromWindow(getWindow().getCurrentFocus()
                    .getWindowToken(), 0);
        }
    }
    boolean ret = super.dispatchTouchEvent(event);
    return ret;
}


回答2:

As I wrote in Gabrjan's post's comments that this fires continuously while touching the screen, there's actually an easy way to get only the touch down events:

@Override
public boolean dispatchTouchEvent(MotionEvent event) {
    if (event.getAction() == MotionEvent.ACTION_DOWN) {
        System.out.println("TOUCH DOWN!");
        //set immersive mode here, or whatever...
    }
    return super.dispatchTouchEvent(event);
} 

This was very useful to me to put the Android into immersive mode whenever any part of the screen was touched regardless which element. But I didn't wish to set immersive mode repeatedly!



回答3:

ok, now i'm sure that the problem is that scrollview handle touches, so anyway to ignore that and yet be the scrolling avaiable?

Yes that's the problem, when android handles touch events each event goes from child to parent, so first it's handled by ViewFlipper, but then it goes to ScrollView. So you have to implement getParent().requestDisallowInterceptTouchEvent(true) (see ViewParent class) in order to make all touch events handled by ViewFlipper, and then simply detect the direction of gesture if horizontal then flip view if not then pass touch event to ScrollView or just scroll ScrollView programmatically

EDIT: Also you can implement OnTouchListener in your ViewFlipper and in this listener trigger GestureDetector.onTouchEvent(event), but this also requires requestDisallowInterceptTouchEvent of your parent view set to true



回答4:

All gestures and touch events goes to the lowest element in view hierarchy who can handle it. So if you have any listener in included layout you can call ((TypeOfParrent)yourView.getParent()).onTouchEvent(event) to delegate event to the handler you want.

ADD: I recoment you to use ViewPager for flipping views. In the ViewPager you dont need to implements your own onGestureListener.

http://www.edumobile.org/android/android-beginner-tutorials/view-pager-example-in-android-development/

http://developer.android.com/reference/android/support/v4/view/ViewPager.html