Android - show soft keyboard automatically upon activity or fragment creation

     One of the frequent problems in Activities is to show the keyboard automatically upon activity creation. This makes sense especially when the first interaction is to enter some text into text fields like creating an event in calendar, search application, or a banking application with focus on username. It is kind of a pain for the user to click on the text field in spite of focus being on the text field. This is even more obvious in a big screen device with the Edit Text being on the top half and user having to reach out just to show the keyboard. So the quick solution, is to listen for focus change and request for the keyboard to be shown (an activity having just an EditText).


        editText.setOnFocusChangeListener(new android.view.View.OnFocusChangeListener() {

            @Override
            public void onFocusChange(final View v, boolean hasFocus) {
                mImm.showSoftInput(editText, InputMethodManager.SHOW_FORCED);
            }

        });

However, this doesn't seem to work. So the next possible solution is to post a runnable from onFocusChange,

       editText.setOnFocusChangeListener(new android.view.View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(final View v, boolean hasFocus) {

                editText.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        mImm.showSoftInput(editText, InputMethodManager.SHOW_FORCED);
                    }
                }, 100);
            }
        });

    Now i got different results for the above code. In some cases, posting a runnable without any delay would work and in some cases the delay varies between 100 to 500 milli seconds. The ugly solution is to post the runnable after a second or so. But that really sucks, there must be some logic which should be deterministic. So the following solution finally worked for all cases and even fragments,

public class MyEditText extends EditText {
    public MyEditText(Context context) {
        super(context);
    }

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

    public MyEditText(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public void onWindowFocusChanged(boolean hasWindowFocus) {
        super.onWindowFocusChanged(hasWindowFocus);
        if (hasWindowFocus) {
            imm.showSoftInput(this, InputMethodManager.SHOW_FORCED);
        }
    }
}

The idea is to have a custom EditText implementation and to override onWindowFocusChanged. Its important to show the keyboard only after super.onWindowFocusChanged(). The super functionality invokes a input method manager specific logic in a View. It sets the view to be next served view for input method. Any attempt to show keyboard before that doesn't even dispatch a request to Android Framework. This explains as to why onFocusChange doesn't help as that happens to be called before the view's onWindowFocusChanged and also as to why posting a delayed runnable works in some cases.


No comments: