Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android TabHost tabs steal focus when using Hardware Keyboard

I currently have a TabHost containing 4 tabs. On a few of the fragments we have a number of EditText views within the layout.

We have noticed that when you attempt to type into any of the EditText views using the hardware keyboard, the focus is stolen from the EditText and given to the currently active tab in the TabHost. This only occurs on screens with tabs. Is there a quick and simple way to solve this?

like image 295
Michael Muesch Avatar asked Mar 27 '13 20:03

Michael Muesch


3 Answers

This has been a known bug for quite a long time:

http://code.google.com/p/android/issues/detail?id=2516

A workaround would be forcing the TabHost to lose focus after a tab is selected. This is done by setting a OnTabChangeListener for the TabHost and calling clearFocus in the onTabChanged method.

tabHost.setOnTabChangedListener(new OnTabChangeListener(){    
    public void onTabChanged(String tabID) {    
        tabHost.clearFocus(); 
    }   
}); 

EDIT: If this doesn't work you can try the other way around. Forcing the EditText fields to gain focus instead:

OnTouchListener focusHandler = new OnTouchListener() {
    @Override
    public boolean onTouch(View view, MotionEvent event) {
        // TODO Auto-generated method stub
        view.requestFocusFromTouch();
        return false;
    }
};

editText.setOnTouchListener(focusHandler); //For each EditText with this issue
like image 87
Leon Lucardie Avatar answered Nov 09 '22 00:11

Leon Lucardie


I found this solution at http://code.google.com/p/android/issues/detail?id=2516 and it works better than any of the solutions here or on the bug report page, because it addresses the root cause instead of working around it. I'll let the author (g1adrift) explain:

After digging extensively through the Android source, I found the bug: TabHost registers an OnTouchModeChangeListener in onAttachedToWindow() that steals focus when leaving touch mode (aka when someone presses a key) if the current tab content view doesn't have focus. While this may make sense if the whole layout is tabbed, if there is only a portion of the layout that has tabs, it causes issues.

This workaround removes that listener, so all artifacts of using it should go away:

in onCreate(), add:

TabHost mTabHost = (TabHost) findViewById(android.R.id.tabhost);
mTabHost.addOnAttachStateChangeListener(new OnAttachStateChangeListener() {

    @Override
    public void onViewDetachedFromWindow(View v) {}

    @Override
    public void onViewAttachedToWindow(View v) {
        mTabHost.getViewTreeObserver().removeOnTouchModeChangeListener(mTabHost);
    }
});

It supposedly only works for SDK 12+. The author also posted a solution for earlier SDKs. If you need it, click the link above and search for posts by "g1adrift".

like image 3
Barry Fruitman Avatar answered Nov 09 '22 01:11

Barry Fruitman


 @Override
    public void onPageSelected(int position) {
        // Unfortunately when TabHost changes the current tab, it kindly
        // also takes care of putting focus on it when not in touch mode.
        // The jerk.
        // This hack tries to prevent this from pulling focus out of our
        // ViewPager.
        TabWidget widget = mTabHost.getTabWidget();
        int oldFocusability = widget.getDescendantFocusability();
        widget.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
        mTabHost.setCurrentTab(position);
        widget.setDescendantFocusability(oldFocusability);

    }

copy-paste from android support library examples

like image 1
Artem Zelinskiy Avatar answered Nov 08 '22 23:11

Artem Zelinskiy