Android Tip: Resize the application for the soft-keyboard with windowSoftInputMode

Android Tip: Resize the application for the soft-keyboard with windowSoftInputMode

    Android has Input Method Framework to support different input methods, e.g. keyboard, soft-keyboard, handwriting etc. If the soft-keyboard is used it is displayed at the bottom of the screen once the user select an text view to edit it.
    This way it may overlay other views as Android scrolls the application window so that the selected view is visible and shows the soft-keyboard. This approach is called "pan and scan" and is the default behavior in Android.

    Suppose we have a layout with many TextInputLayouts like this:
activity_input.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="info.devexchanges.softinputwindow.InputActivity">


    <android.support.design.widget.TextInputLayout
        android:id="@+id/full_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="Full Name"
            android:inputType="text" />

    </android.support.design.widget.TextInputLayout>

    <android.support.design.widget.TextInputLayout
        android:id="@+id/age"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="Age"
            android:inputType="number" />

    </android.support.design.widget.TextInputLayout>

    <android.support.design.widget.TextInputLayout
        android:id="@+id/phone_number"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="Phone Number"
            android:inputType="phone" />

    </android.support.design.widget.TextInputLayout>

    <android.support.design.widget.TextInputLayout
        android:id="@+id/email"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="Email"
            android:inputType="textEmailAddress" />

    </android.support.design.widget.TextInputLayout>

    <android.support.design.widget.TextInputLayout
        android:id="@+id/address"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="Address"
            android:inputType="textEmailAddress" />

    </android.support.design.widget.TextInputLayout>

    <android.support.design.widget.TextInputLayout
        android:id="@+id/company"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="Company"
            android:inputType="textEmailAddress" />

    </android.support.design.widget.TextInputLayout>

    <Button
        android:id="@+id/submit"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Submit" />
</LinearLayout>
    When running this activity, we'll have this output:

    If you select the "full name" field, the result may look like the following. "Pan and scan" overlays some edit texts and the button below it:

    You can change this behavior to "resize". If your application has enough space the layout would be adjusted to show all views together with the keyboard (the layout will move up when the soft-keyboard is shown).
    To change the mode to "resize" at the following statement, add windowSoftInputMode feature with adjustResize as the value to your activity declaration in AndroidManifest.xml:
        <activity
            android:name=".MainActivity"
            android:windowSoftInputMode="adjustResize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    But in this case, there are a lot of TextInputLayouts in our layout, so you must put them inside a ScrollView or NestedScrollView as the root container layout:
  activity_input.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="info.devexchanges.softinputwindow.MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <android.support.design.widget.TextInputLayout
            android:id="@+id/full_name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Full Name"
                android:inputType="text" />

        </android.support.design.widget.TextInputLayout>

        <android.support.design.widget.TextInputLayout
            android:id="@+id/age"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Age"
                android:inputType="number" />

        </android.support.design.widget.TextInputLayout>

        <android.support.design.widget.TextInputLayout
            android:id="@+id/phone_number"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Phone Number"
                android:inputType="phone" />

        </android.support.design.widget.TextInputLayout>

        <android.support.design.widget.TextInputLayout
            android:id="@+id/email"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Email"
                android:inputType="textEmailAddress" />

        </android.support.design.widget.TextInputLayout>

        <android.support.design.widget.TextInputLayout
            android:id="@+id/address"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Address"
                android:inputType="textEmailAddress" />

        </android.support.design.widget.TextInputLayout>

        <android.support.design.widget.TextInputLayout
            android:id="@+id/company"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Company"
                android:inputType="textEmailAddress" />

        </android.support.design.widget.TextInputLayout>

        <Button
            android:id="@+id/submit"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Submit" />
    </LinearLayout>
</android.support.v4.widget.NestedScrollView>
    And we'll have this result when app running:

    Important Note: TextInputLayout and NestedScrollView are widgets of Design Support Library, in order to use it you must add this dependency to dependencies scope of your app-level build.gradle:
compile 'com.android.support:design:24.2.1'
    Through this tip, I hope it's helpful to make user input data easier, contributes to improve UX on your application. Moreover, some references links you should take a glance:
Android Basic Training Course: The Input Method

Android Basic Training Course: The Input Method

    Android introduces input method framework (IMF), commonly known as soft keyboard. However, this term is not necessarily accurate, because the IMF can be used for handwriting recognition or other means of acceptable text input via the screen.
    Only some Android devices with hardware keyboards and most of them have soft keyboards only. IMF handle all input works.
    Usually, if there is no hardware keyboard, an input method editor (IME) will be availabled to users when they click on an EditText. If the default function of percussion is what you want to offer, you do not need to make any changes to your application code. Fortunately, Android is pretty clever to guess what you want, so you may need to experiment with IME and specific without changing code.
    However, percussion IME can not totally fit for your application. For example, It may covered many of EditText line. It would be nice if we can control the behavior of IME. Fortunately, the IMF as an overall tool gives you many options for this, will be described in this post.

Choose input type for EditText

    EditText has a attribute called android:inputType, by this, we can set the the suitable input type for our aim. Look at this example:     With the EditText hasn't been set input type (no special rule), a default soft keyboard without special characters will be shown when it's focused:
    If input type value is textEmailAddress, we will have a @ character in soft keyboard interface, the DONE key is displayed with "Send icon" when we set android:imeOptions="actionSend":
    Input type value is textPassword, all input texts will be hidden:
   We can allowed user input only number to EditText by set input type is number, numberSigned or numberDecimal:
   And the date input type is have "/" character in bottom left corner:
    Moreover, you can enlarge the EditText (not is only 1 line) interface by set input type to textMultiline and use attributes minLines, maxLines:

Force Hiding Soft Keyboard

    Soft keyboard will appear when an EdiText is focused. Sometimes, we would like to hide it by touching at screen (outside the EditText). This work can be done by overriding dispatchTouchEvent() method to detect touching action from user (if we touch outside, softkeyboard will hide and the EditText will be unfocused):
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        View v = getCurrentFocus();
        if (v != null &&
                (ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_MOVE) &&
                v instanceof EditText &&
                !v.getClass().getName().startsWith("android.webkit.")) {
            int scrcoords[] = new int[2];
            v.getLocationOnScreen(scrcoords);
            float x = ev.getRawX() + v.getLeft() - scrcoords[0];
            float y = ev.getRawY() + v.getTop() - scrcoords[1];

            if (x < v.getLeft() || x > v.getRight() || y < v.getTop() || y > v.getBottom())
                hideKeyboard(this);
        }
        return super.dispatchTouchEvent(ev);
    }

    public static void hideKeyboard(Activity activity) {
        if (activity != null && activity.getWindow() != null && activity.getWindow().getDecorView() != null) {
            InputMethodManager imm = (InputMethodManager)activity.getSystemService(Context.INPUT_METHOD_SERVICE);
            imm.hideSoftInputFromWindow(activity.getWindow().getDecorView().getWindowToken(), 0);
        }
    }

Conclusions

     Through this tip, I hope you can understand about IMF/IME of Android and cane choose suitable input type for each EditText.  More details, you can go to read the official doc page about InputMethodManager or visit this tag link to read all posts about EditText and input.