How to show soft keyboard perfectly in fragment in Android?

Waylent picture Waylent · Aug 30, 2016 · Viewed 15.9k times · Source

I have an EditText inside a Fragment inside a Activity.

My Activity layout:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@drawable/login_bg">
    ...

    <FrameLayout
        android:id="@+id/fragment_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    ...

</RelativeLayout>

My Activity config in AndroidManifest.xml:

    <activity
        android:name="com.demo.LoginActivity"
        android:configChanges="orientation|keyboardHidden"
        android:launchMode="singleTop"
        android:screenOrientation="portrait"
        android:theme="@style/activityTheme" />

My code that use to start fragment in Activity:

private void startFragment(BaseFragment fragment, String tag) {
    FragmentManager fragmentManager = getSupportFragmentManager();
    FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
    fragmentTransaction.add(R.id.fragment_container, fragment);
    fragmentTransaction.addToBackStack(tag);
    fragmentTransaction.commitAllowingStateLoss();
}

My Fragment layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/common_background_color_white"
    android:orientation="vertical"
    android:clickable="true"
    android:paddingLeft="@dimen/email_common_padding_horizontal"
    android:paddingRight="@dimen/email_common_padding_horizontal">

    ...

    <com.example.widget.LineEditView
        android:id="@+id/login_email_input"
        style="@style/BaseEditText.LoginEditText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:focusable="true"
    />

    ...

</LinearLayout>

My Custom Widget LineEditView is a child class extend RelativeLayout,and it layout:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/input"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <EditText
        android:id="@+id/edit"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:focusable="true"
        android:gravity="start|center_vertical"
        android:background="@android:color/transparent"
        android:textColor="@color/common_text_color_black"
        android:maxLines="1"
        android:textCursorDrawable="@drawable/common_cursor_background_orange"
        android:textSize="@dimen/email_fields_text_size"
        android:paddingBottom="@dimen/email_fields_text_padding_bottom"/>

    <View
        android:id="@+id/underline"
        android:layout_below="@id/edit"
        android:layout_width="match_parent"
        android:layout_height="2px"/>
</RelativeLayout> 

I want to show soft keyboard according to inputType property of EditText,and can hide easily.

What I have tried but not work or not perfect:

1.According to Show keyboard for edittext when fragment starts can show soft keyboard but can not hide easily(even can not hide sometimes) and it show keyboard not according to inputType property of EditText.

2.I add following code to My Fragment:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container) {
    mEditText = (EditText) rootView.findViewById(R.id.edit);
    mEditText.requestFocus();
    mEditText.setFocusable(true);
}

@Override
public void onResume() {
    mEditText.postDelayed(mShowSoftInputRunnable, 400);
    super.onResume();
}

private Runnable mShowSoftInputRunnable = new Runnable() {
    @Override
    public void run() {
        FragmentActivity activity = getActivity();
        if (activity == null)
            return;

        InputMethodManager input = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
        input.showSoftInput(mEditText, InputMethodManager.SHOW_IMPLICIT);
    }
};

but it can not show soft keyboard at all in my fragment.

I can not put EditText to Activity because it need to refactor a lot of code.

Does anyone have ideas to solve this problems?

Answer

apmartin1991 picture apmartin1991 · Aug 30, 2016

Here is the code I use which works very well in Fragments

public static void hideKeyboard(Context context) {
    try {
        ((Activity) context).getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
        if ((((Activity) context).getCurrentFocus() != null) && (((Activity) context).getCurrentFocus().getWindowToken() != null)) {
            ((InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(((Activity) context).getCurrentFocus().getWindowToken(), 0);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

public static void showKeyboard(Context context) {
    ((InputMethodManager) (context).getSystemService(Context.INPUT_METHOD_SERVICE)).toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY);
}