Android片段中如何完美显示软键盘?

How to show soft keyboard perfectly in fragment in Android?

我在 Activity.

的 Fragment 中有一个 EditText

我的Activity布局:

<?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>

我的 Activity 配置 AndroidManifest.xml:

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

我在 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();
}

我的 Fragment 布局:

<?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>

我的自定义小部件 LineEditView 是子 class 扩展 RelativeLayout,它的布局:

<?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> 

我想根据EditText的inputType属性显示软键盘,而且可以轻松隐藏。

我尝试过但没有效果或不完美的方法:

1.According到Show keyboard for edittext when fragment starts可以显示软键盘但不能轻易隐藏(有时甚至不能隐藏)并且显示键盘不符合EditText的inputType 属性。

2.I 将以下代码添加到我的片段:

@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);
    }
};

但在我的片段中它根本无法显示软键盘。

我不能把EditText放到Activity因为它需要重构很多代码

有没有人有解决这个问题的想法?

这是我使用的代码,它在 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);
}

hideSoftKeyboard

在fragment中需要隐藏键盘时调用

hideSoftKeyboard(getActivity());

调用函数

  private void hideSoftKeyboard(Activity activity)
{
    InputMethodManager inputMethodManager = (InputMethodManager)  activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
    inputMethodManager.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0);
}

showSoftKeyboard

你调用它是为了在框架中显示键盘并传递编辑文本

 EditText edittext=(EditText) findViewById(R.id.edittext);
 showSoftKeyboard(edittext);

调用这个函数

 public void showSoftKeyboard(View view) {
    InputMethodManager inputMethodManager = (InputMethodManager)getActivity(). getSystemService(Activity.INPUT_METHOD_SERVICE);
    view.requestFocus();
    inputMethodManager.showSoftInput(view, 0);
}