No implementation of GestureDetector will work on android app

408 views Asked by At

I am trying to add a GestureDetector to an activity in my app. I have tried several different methods from youtube and stackoverflow none are working. No errors are showing and nothing happens when I swipe or use any gesture. I have put debugging logs all along the way and none are registering in the logcat Im all out of ideas now. It is the onFling() method I am mainly interested in.

I am putting up two methods i have tried. I have removed some code and changed it to make more reader friendly and relevant.

If anyone can help Id be delighted.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical">

    <!-- LinearLayout has two children, Toolbar & DrawerLayout.
            DrawerLayout has two children RelativeLayout (main content container) 
            LinearLayout is the root element so the Navigationdrawer does not open over the Toolbar.
            The DrawerLayout was the root element before this.-->


    <!-- adding the toolbar layout -->
    <include
        android:id="@+id/toolbar"
        layout="@layout/toolbar"/>


<android.support.v4.widget.DrawerLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/mainDrawerLayout">


         <RelativeLayout 
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    <ImageView
        android:id="@+id/backgroundImg"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop"
        android:src="@drawable/nipple"
        android:contentDescription="@string/content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true" />


             <TextView android:id="@+id/main_tv"
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
                 android:padding="10dp"
                 android:gravity="center"
                 android:text="Hello"/>

    </RelativeLayout>

    <fragment android:id="@+id/fragment_navigation_drawer"
        android:layout_width="280dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:layout="@layout/fragment_navigation_drawer"
        android:name="com.ansgar.amazingfacts.activities.FragmentNavigationDrawer"
        tools:layout="@layout/fragment_navigation_drawer"/>


</android.support.v4.widget.DrawerLayout>
    </LinearLayout>

Method 1 Defining custom listener class

public class MainActivity extends AppCompatActivity implements FragmentNavigationDrawer.FragmentNavigationDrawerListener {
    private ImageView image;
    private TextView mTextView;
    private Toolbar mToolbar;
    private FragmentNavigationDrawer drawerFragment;
    GestureDetectorCompat gesture;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        image = (ImageView) findViewById(R.id.backgroundImg);
        mTextView = (TextView) findViewById(R.id.main_tv);
        mToolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(mToolbar);
        getSupportActionBar().setDisplayShowHomeEnabled(true);
        //Fragment for navigation drawer
        drawerFragment = (FragmentNavigationDrawer) getSupportFragmentManager().findFragmentById(R.id.fragment_navigation_drawer);
        //This method is created because we need to pass a few things from MainActivity to the FragmentNavigationDrawer
        drawerFragment.sepUp(R.id.fragment_navigation_drawer, (DrawerLayout) findViewById(mainDrawerLayout), mToolbar);
        drawerFragment.setDrawerListener(this);

        this.gesture = new GestureDetectorCompat(this, new CustomGestureClass());

    }//onCreate()



    @Override
    public boolean onTouchEvent(MotionEvent event) {
        this.gesture.onTouchEvent(event);
        Log.d("GESTURE", "OnTouchEvent");
        Toast.makeText(getApplicationContext(), "Touch event", Toast.LENGTH_SHORT).show();
        return super.onTouchEvent(event);
    }


        class CustomGestureClass extends GestureDetector.SimpleOnGestureListener {
            //SimpleOnGestureListener is listener for what we want to do and how

            @Override
            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
                //return super.onFling(e1, e2, velocityX, velocityY);
                Log.d("GESTURE", "OnFling");
                float sensitivity = 50;
                //swipe left check
                if (e1.getX() - e2.getX() > sensitivity) {
                    Log.d("GESTURE", "swipe left");
                    return true;
                }

                //swipe right check
                if (e2.getX() - e1.getX() > sensitivity) {
                    Log.d("GESTURE", "Swipe Right");
                    Toast.makeText(getApplicationContext(), "Swipe right gesture", Toast.LENGTH_SHORT).show();
                    return true;
                }

                //swipe check down
                if (e1.getY() - e2.getY() > sensitivity) {
                    Log.d("GESTURE", "Swipe Down");
                    Toast.makeText(getApplicationContext(), "Swipe down gesture", Toast.LENGTH_SHORT).show();
                    return true;
                }

                //swipe up check
                if (e2.getY() - e1.getY() > sensitivity) {
                    Log.d("GESTURE", "Swipe Up");
                    Toast.makeText(getApplicationContext(), "Swipe up gesture", Toast.LENGTH_SHORT).show();
                    return true;
                }

                return true;
                //return false;
            }

            @Override
            public boolean onDown(MotionEvent e) {
                Log.d("GESTURE", "OnDown");
                //return super.onDown(e);
                return true;
            }
        }//CustomGestureClass



    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        return true;

    }

    //setting the title of actionBar
    public void setTitle(String title){
        getSupportActionBar().setTitle(title);
    }

    public void onCreateDrawer() {}

    @Override
    public void onDrawerItemSelected(View view, int position){
        displayView(position);
        //Log.d("DRAWER ITEM SELECTED", "the index number of item Drawer RecyclerView "+ position);
        switch(position){

            case 0:
                break;
        }
    }

    private void displayView(int position) {}

}//MainActivity.class

Method 2

public class MainActivity extends AppCompatActivity implements FragmentNavigationDrawer.FragmentNavigationDrawerListener,
    GestureDetector.OnGestureListener {

    private ImageView image;
    private TextView mFactTextView;
    private Toolbar mToolbar;
    private FragmentNavigationDrawer drawerFragment;
    GestureDetectorCompat gesture;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        image = (ImageView) findViewById(R.id.backgroundImg);
        mTextView = (TextView) findViewById(R.id.main_tv);
        mToolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(mToolbar);
        getSupportActionBar().setDisplayShowHomeEnabled(true);
        //Fragment for navigation drawer
        drawerFragment = (FragmentNavigationDrawer) getSupportFragmentManager().findFragmentById(R.id.fragment_navigation_drawer);
        //This method is created because we need to pass a few things from MainActivity to the FragmentNavigationDrawer
        drawerFragment.sepUp(R.id.fragment_navigation_drawer, (DrawerLayout) findViewById(mainDrawerLayout), mToolbar);
        drawerFragment.setDrawerListener(this);


        this.gesture = new GestureDetectorCompat(this, this);

    }//onCreate()


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        this.gesture.onTouchEvent(event);
        Log.d("GESTURE", "OnTouchEvent");
        Toast.makeText(getApplicationContext(), "Touch event", Toast.LENGTH_SHORT).show();
        return super.onTouchEvent(event);
    }


    @Override
    public boolean onDown(MotionEvent e) {
        Log.d("GESTURE", "OnDown");
        return true;
    }

    @Override
    public void onShowPress(MotionEvent e) {
        Log.d("GESTURE", "OnShowPress");
    }

    @Override
    public boolean onSingleTapUp(MotionEvent e) {
        Log.d("GESTURE", "OnSingleTapUp");
        return true;
    }

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
        Log.d("GESTURE", "OnScroll");
        return true;
    }

    @Override
    public void onLongPress(MotionEvent e) {
        Log.d("GESTURE", "OnLongPress");
    }

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        Log.d("GESTURE", "OnFling");
        return true;
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }


    public void onCreateDrawer() {}


    @Override
    public void onDrawerItemSelected(View view, int position){
        displayView(position);
        //Log.d("DRAWER ITEM SELECTED", "the index number of item Drawer RecyclerView "+ position);
        switch(position){
            case 0:
                break;
        }
    }

    private void displayView(int position) {}


}//MainActivity.class
1

There are 1 answers

2
John Le On

Concerning to the document of onTouchEvent(event) method: "Called when a touch screen event was not handled by any of the views under it. This is most useful to process touch events that happen outside of your window bounds, where there is no view to receive it.". So you should check:

  1. There is a child view that was handled the event in the activity or not (that means the onTouchEvent(event) method of this child view returns "true"). If no, go to number 2

  2. The onTouchEvent(event) method of the activity should be returned "true".(according the document: "Return true if you have consumed the event, false if you haven't. The default implementation always returns false" -> using return super.onTouchEvent(event); always returns "false")

Hope it can help you