如何在一个片段中隐藏软键盘?

97

我有一个FragmentActivity,使用ViewPager来呈现多个片段。每个片段都是一个带有以下布局的ListFragment

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="8dp">
        <ListView android:id="@id/android:list"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent" />

        <EditText android:id="@+id/entertext"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content" />
    </LinearLayout>
</LinearLayout>

开始运行活动时,软键盘会显示出来。为了解决这个问题,我在片段中执行了以下操作:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    //Save the container view so we can access the window token
    viewContainer = container;
    //get the input method manager service
    imm = (InputMethodManager)getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
    . . .
}

@Override
public void onStart() {
    super.onStart();

    //Hide the soft keyboard
    imm.hideSoftInputFromWindow(viewContainer.getWindowToken(), 0);
}

在onCreateView中,我保存了传入的ViewGroup容器参数作为一种访问主活动窗口令牌的方式。虽然没有错误,但是在onStart中调用hideSoftInputFromWindow时,键盘并没有隐藏。

最初,我尝试使用充气布局而不是container,即:

imm.hideSoftInputFromWindow(myInflatedLayout.getWindowToken(), 0);

可是这样做会抛出NullPointerException,可能是因为片段本身不是一个活动并且没有唯一的窗口标记吗?

是否有一种方法可以在片段内隐藏软键盘,或者我应该在FragmentActivity中创建一个方法并从片段内调用它?

19个回答

199
只要你的Fragment创建了一个View,你就可以在它被附加后使用该View中的IBinder(窗口标记)。例如,你可以在Fragment中重写onActivityCreated方法:
@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    final InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(getView().getWindowToken(), 0);
}

9
我已经将这个添加到我的项目中,但是当我点击其他标签页时它会崩溃。 - andro-girl
4
对于那些使用时遇到NullPointerException崩溃的人,只需在片段(fragment)的onCreateView方法中使用InputMethodManager即可解决问题。这样做,您将拥有视图,并且可以使用您已经膨胀(inflated)的视图来更改最后一行,用以下代码替换:imm.hideSoftInputFromWindow(view.getWindowToken(), 0); - Aurasphere
完美的答案,我建议在onResume中添加相同的功能来处理在viewpager内创建多个片段并且其中一个需要在创建后隐藏键盘的情况。 - Sherif farid
谢谢,但是这个方法已经被弃用了。最好建议另一个解决方案... - Mohamad Seyedi

91

对我来说,只有以下这行代码有效:

getActivity().getWindow().setSoftInputMode(
            WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);

2
SOFT_INPUT_STATE_HIDDEN 对我也起作用,但我不知道它和 SOFT_INPUT_STATE_ALWAYS_HIDDEN 之间的区别是什么。 - hBrent
2
第一个答案没用,这个解决了问题。谢谢。 - moujib
1
谢谢你帮我节省时间,伙计。 - Harish Reddy
我的情况是我正在使用Fragment/TabView。第一个选项卡在TextView中显示“提示”。第二个选项卡有一个活动,在这个活动中,我有带有“editText1.setShowSoftInputOnFocus(false);”命令设置和我自己的定制键盘的EditText(s)。当我把应用程序放到后台,然后再次将应用程序带回视图时,不需要的软键盘会弹出。在onStart生命周期覆盖方法中设置上述命令可以停止这种情况。谢谢@Shajeel Afzal - user9329083

23
如果您将以下属性添加到活动的清单定义中,则可以完全防止键盘在打开活动时弹出。希望这能有所帮助:
(添加到Activity的清单定义中):
android:windowSoftInputMode="stateHidden"

谢谢,这就是我最终做的。但是,我仍然想知道如何使用输入法管理器来显示/隐藏键盘,因为我在活动开始后可能需要使用它。 - WilHall

14
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_my, container,
                false);
        someClass.onCreate(rootView);
        return rootView;
    }
保持我的根视图的一个实例在我的类中。
View view;

public void onCreate(View rootView) {
    view = rootView;

使用视图来隐藏键盘

 public void removePhoneKeypad() {
    InputMethodManager inputManager = (InputMethodManager) view
            .getContext()
            .getSystemService(Context.INPUT_METHOD_SERVICE);

    IBinder binder = view.getWindowToken();
    inputManager.hideSoftInputFromWindow(binder,
            InputMethodManager.HIDE_NOT_ALWAYS);
}

我使用了这个,但是我从我的片段中使用了getView()而不是保留我的视图实例。 - MrEngineer13
onCreate是Fragment外的一个类,因此我将rootView传递给它,以便在该类中使用它来移除phoneKeyPad。我想他们希望从Fragment内部而不是Fragment中的类中获取它。 - Mobile Applications

11

不过对于DialogFragment来说,嵌入的Dialog的焦点必须隐藏,而只有嵌入的Dialog中的第一个EditText才能显示焦点。

this.getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);

5
这是在使用DialogFragment时隐藏键盘的唯一方法。 - Matjaz Kristl
在哪里写这个? - Mstack
@Mstack,在onActivityCreated()方法上工作。`override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN)} ` - Sami Issa

9

这段代码适用于片段:

getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);

5

您可以在任何地方(活动/片段)使用此静态方法。

public static void hideKeyboard(Activity activity) {
    try{
        InputMethodManager inputManager = (InputMethodManager) activity
                .getSystemService(Context.INPUT_METHOD_SERVICE);
        View currentFocusedView = activity.getCurrentFocus();
        if (currentFocusedView != null) {
            inputManager.hideSoftInputFromWindow(currentFocusedView.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
        }
    }catch (Exception e){
        e.printStackTrace();
    }
}

如果您想在片段中使用,请调用hideKeyboard(((Activity) getActivity()))。这将隐藏键盘。

4

以下是在片段中对我有效的解决方案:

fun hideKeyboard(){
    val imm = requireActivity().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
    imm.hideSoftInputFromWindow(view?.windowToken, 0)
}

还有在一个活动中:

fun hideKeyboard(){
    val inputManager: InputMethodManager = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
    inputManager.hideSoftInputFromWindow(currentFocus?.windowToken, InputMethodManager.SHOW_FORCED)
}

3

当我在选项卡中从一个片段切换到另一个片段时,这将在我的情况下起作用。

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (isVisibleToUser) {
        try {
            InputMethodManager mImm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
            mImm.hideSoftInputFromWindow(getView().getWindowToken(), 0);
            mImm.hideSoftInputFromWindow(getActivity().getCurrentFocus().getWindowToken(), 0);
        } catch (Exception e) {
            Log.e(TAG, "setUserVisibleHint: ", e);
        }
    }
}

如果您有选项卡片段并且只想为几个选项卡隐藏键盘,请使用此功能。 - Ronny Sulistio

2

这些方法在API27上都不起作用。我必须将其添加到布局的容器中,对我来说,容器是ConstraintLayout:

<android.support.constraint.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:focusable="true"
            android:focusableInTouchMode="true"
            android:focusedByDefault="true">

//Your layout

</android.support.constraint.ConstraintLayout>

它在 API < 26 上无法工作,但这个可以(在片段类内部) @Override public void onResume() { super.onResume(); getView().setFocusable(true); getView().setFocusableInTouchMode(true); getView().requestFocus(); } - Dark

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接