Android Tabs with 'fling' change
Android Tabs with 'fling' change

Developing for android has this type of things. You need to support older versions of the OS, with older ways of interacting with the user, but at the same time provide a more up-to-date experience.

Tabs on android were (on android 2.*) only changeable by pressing on each of the individual tabs on the TabWidget. Nowadays everyone expects to be able to change tabs with a simple swipe left or right, so some hacking is called for. Here is my solution (there might be a simpler, easier way, that I'm not aware of).

Quick How to

  1. Use a android.gesture.GestureOverlayView as the child of the TabHost and place the original contents inside that element;
  2. in the activity with tabs implement the support for listening to the gestures;
  3. set the GestureOverlayView to invisible gestures and make the activity the listener for the gestures;
  4. store the position and time of when a gesture starts;
  5. when a genture end compare the end position and time to the initial gesture event. If it's a swipe then tell tab host to change the current tab;
  6. add animations to make it feel more realistic. This is actually more complex than it should:

    1. when you detect the swipe give the current tab view a animation so that it slides out (to the left or right, depending on the direction of the slide)
    2. the activity should implement the OnTabChangeListener and the TabHost should have the activity as a listener;
    3. on a onTabChanged event then create a animation for the new tab. When it's a change due to a swipe I do a slide in animation, but if it is a change because the user pressed the TabWidget then I do a quick fade in animation.

The reason to use the GestureOverlayView is that it guarantees that we receive the MotionEvent. If we just listen for events (like onFling) in the activity then some events will not reach us as they will be consumed by the children widgets.

This works well when the tabs are horizontally laid (as when the device is in portrait mode) but for landscape (with the tabs laid vertically) it makes no sense as it interferes with the scrolling of the views within the activity. Anyway.. I'm starting to feel that this tabs really don't work for landscape and tablets…

I'll post some code and layouts about this soon.