Search code examples
androidtabsontouchlistenerfragment-tab-hostgesturedetector

Touch Events Inside ActionBarActivity


I have three tabs inside a support7 ActionBarActivity which contains a support4 FragmentTabHost. It is largely working and tapping on the tab titles switches to the correct Fragment.

I'm trying to add a GestureDetector so that swiping left/right will change tabs. (I know there are more modern containers for this but lets stick with FragmentTabHost for now.)

class MainGestureDetector extends GestureDetector.SimpleOnGestureListener {
    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        try {
            if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH)
                return false;
            final int current = tabHost.getCurrentTab();
            if(e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
                if (current < tabHost.getTabWidget().getTabCount() - 1) {
                    tabHost.setCurrentTab(current + 1);
                }
            }  else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
                if (current > 0) {
                    tabHost.setCurrentTab(current - 1);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return super.onFling(e1, e2, velocityX, velocityY);
    }

    @Override
    public boolean onDown(MotionEvent e) {
        return true;
    }
}

and instantiated as such:

    gestureDetector = new GestureDetector(this, new MainGestureDetector());
    gestureListener = new View.OnTouchListener() {
        public boolean onTouch(View v, MotionEvent event) {
            return gestureDetector.onTouchEvent(event);
        }
    };

    tabHost = (FragmentTabHost) findViewById(android.R.id.tabhost);
    tabHost.setup(this, getSupportFragmentManager(), android.R.id.tabcontent);

    tabHost.setOnClickListener(this);
    tabHost.setOnTouchListener(gestureListener);

It works! But only on the very first tab. Once swiping (or tapping) switches to a tab other than the first, swiping doesn't work. If I tap on the first tab again to go back to the beginning, the gesture recognizer will again work... once.

What do I have to do to make the GestureListener work on all tabs?


Solution

  • I guess I should have realized. The "touch" events were getting directed to child views within the tab rather than propagate up to the parent and the GestureListener I had defined there. My first tab didn't (yet) have a child view spanning the screen so that is why it worked there.