5

I have a fragment within a TabHost that has multiple text fields in it. The virtual keyboard works just fine to enter text into using inputType set, but the hardware keyboard (on Droid, Droid 2, etc) does not work.

From my testing as soon as you start typing on the hardware keyboard, the EditText loses focus and the "typing" seems to go elsewhere in the application. I have tried both configurations below:

<EditText
     android:id="@+id/editTextPlusFat"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:layout_weight="0.15"
     android:background="@drawable/textfield_default_holo_light"
     android:digits="0123456789."
     android:ems="10"
     android:hint="@string/str_CalcHintFat"
     android:inputType="number" >

AND

<EditText
     android:id="@+id/editTextPlusFat"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:layout_weight="0.15"
     android:background="@drawable/textfield_default_holo_light"
     android:ems="10"
     android:hint="@string/str_CalcHintFat"
     android:inputType="numberDecimal" >

Does anyone have any ideas why this happens? Thank you.

marko
  • 9,029
  • 4
  • 30
  • 46
mattdonders
  • 1,328
  • 1
  • 19
  • 42
  • [Related](http://stackoverflow.com/questions/11277491/edittext-losing-focus-using-hard-keyboard-when-tabhost-is-present-in-activity)? – ioums Jan 04 '13 at 13:48
  • @ioums seems to be exactly related, but does not solve my issue. I tried to `@Override` the onTouchModeChanged method, but it does not work. I even tried to place a `Toast.makeText(...)` inside of the method to make sure it was being called, but the Toast never appears in my app. – mattdonders Jan 06 '13 at 14:09
  • As another note I tried to `getCurrentFocus()` inside of a `onFocusChangeListener()` on the EditText and I see the TabHost trying to steal the focus and there is a `NullPointerException` and in the log I see the `onTouchModeChanged()` trying to be performed on the TabHost, but extending the TabHost and Overriding the function does not seem to work. I have tried it in the Fragment & in the Activity. – mattdonders Jan 07 '13 at 14:04
  • Can you post the nullpointer? – DroidBender Jan 07 '13 at 16:15

2 Answers2

6

My solution was to add onTouchListener() to all EditTexts in each Fragment - see below.

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

currentActivity.findViewById(R.id.editTextPlusServings).setOnTouchListener(foucsHandler);
currentActivity.findViewById(R.id.editTextPlusFoodName).setOnTouchListener(foucsHandler);
mattdonders
  • 1,328
  • 1
  • 19
  • 42
  • I just discovered this in my code too. Have you noticed any side-effects? In other words, is it still working for you? Thanks. – copolii Mar 21 '13 at 21:24
  • Yup still works for me. I find sometimes though when I leave the app, it does a `requestFocusFromTouch()` routine and highlights a different app icon, but its not every time and its not that big of a deal honestly. – mattdonders Mar 25 '13 at 16:12
  • Awesome. Will give it a try today. Thanks. – copolii Mar 26 '13 at 17:00
  • @mattdonders, gr8 solution, tks 4 share it. – vinidog Jul 21 '13 at 04:33
  • @mattdonders The onTouchModeChanged() override does work. So, no need for this. See my other answer. – pjv Jan 11 '14 at 20:49
6

As in the duplicate question, the better answer is to remove the focus switching by overriding onTouchModeChanged() from TabHost.

Add a new class extending TabHost:

package net.lp.collectionista.ui.views;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.TabHost;

public class BugFixedTabHost extends TabHost {

    public BugFixedTabHost(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public BugFixedTabHost(Context context) {
        super(context);
    }

    @Override
    public void onTouchModeChanged(boolean isInTouchMode) {
        // leave it empty here. It looks that when you use hard keyboard,
        // this method would have be called and the focus will be taken.
    }
}

In your Fragment (or Activity) replace the TabHost type with BugFixedTabHost.

Finally, assuming you use TabHost in layout xmls too, change it to your custom view (full package name):

<net.lp.collectionista.ui.views.BugFixedTabHost
    android:id="@android:id/tabhost" ...

I'm not sure why this did not work for @mattdonders, but this is the right way to go. And it is cheaper than attaching listeners to every EditText. By the way, have we figured out yet why mCurrentView.hasFocus() is False or so?

Community
  • 1
  • 1
pjv
  • 10,658
  • 6
  • 43
  • 60
  • The focus problem sometimes happens also for a combination of `TabHost`, soft keyboard, HTML page with text fields opened in a `WebView`. This solution works. – Giulio Piancastelli May 08 '14 at 14:49
  • 1
    This solution works very well. Thanks to share (and works with Genymotion physical keyboard). – Täg Jul 23 '15 at 14:43
  • Yep, this is the best solution. Also it seems the bug exists only on pre-Lollipop versions. – Nikolai Nov 15 '18 at 22:02