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

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个回答

2
这个对我在Kotlin类中有效。
fun hideKeyboard(activity: Activity) {
    try {
        val inputManager = activity
            .getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
        val currentFocusedView = activity.currentFocus
        if (currentFocusedView != null) {
            inputManager.hideSoftInputFromWindow(currentFocusedView.windowToken, InputMethodManager.HIDE_NOT_ALWAYS)
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }

}

1
你刚刚帮我省下了超过48小时的工作时间,兄弟! - truthsayer

1
在 Kotlin 中:
(activity?.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager).hideSoftInputFromWindow(view?.windowToken,0)

1
在任何片段按钮监听器中使用此代码:
InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(getActivity().INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getActivity().getCurrentFocus().getWindowToken(), 0);

可以运行,但是你需要检查 getActivity().getCurrentFocus().getWindowToken() 是否为空,否则如果没有焦点的editText,会导致错误。请参考下面的答案。 - Duc Trung Mai

1

Kotlin代码

val imm = requireActivity().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(requireActivity().currentFocus?.windowToken, 0)

0

你可以使用两种方式:

你可以在片段内创建一个方法,但首先必须创建一个View属性,并将充气器结果放入其中,然后在onCreateView中返回:

1° 打开你的片段类。创建属性

private View view;

第二步,在onCreateView方法中将“view”属性分配为inflater。

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
                view = inflater.inflate(R.layout.your_activity_main, container, false);
                return view;
}

3° 创建方法 'hideKeyboard'

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

第五步:现在只需调用该方法

    hideKeyboard(getActivity());

如果这不能解决你的问题,你可以尝试将MainActivity类作为一个对象传递到Fragment类中来关闭键盘。
1° 在你实例化Fragment的YourClassActivity中,创建一个名为“hideKeyboard”的方法。
public class YourClassActivity extends AppCompatActivity {
    public static void hideKeyboard(Activity activity) {
            InputMethodManager imm = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
            //Find the currently focused view, so we can grab the correct window token from it.
            View view = activity.getCurrentFocus();
            //If no view currently has focus, create a new one, just so we can grab a window token from it
            if (view == null) {
                view = new View(activity);
            }
            imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
        }
}

2° 在实例化Fragment的Activity中实现'Serializable'接口

public class YourClassActivity extends AppCompatActivity implements Serializable {
...
}

3° 当您在 Activity 中实例化 Fragment 时,必须将参数传递给该 Fragment,这些参数将是 Activity 类本身

Bundle bundle = new Bundle();
bundle.putSerializable("activity", this);
YourClassFragment fragment = new YourClassFragment();
fragment.setArguments(bundle);

4° 现在让我们转到您的 Fragment 类。创建视图和活动属性。

private View view;  
private Activity activity;

第五步,在onCreateView方法中将“view”属性分配给inflater。在这里,您将检索作为此Fragment参数传递的Activity对象。

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
            view = inflater.inflate(R.layout.your_activity_main, container, false);
            activity = (Activity) getArguments().getSerializable("obj");
    
            return view;
    }

现在只需调用该方法

hideKeyboard(activity);

0

在开始时

在片段中,以下代码(在onActivityCreated中使用)强制在开始时隐藏键盘:

@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    Objects.requireNonNull(getActivity()).getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
}

在片段期间(如果需要)

如果您有EditText或其他需要键盘的内容,并且希望在键盘外部按下时隐藏键盘(在我的情况下,我在xml中有LinearLayout类),请先初始化布局:

LinearLayout linearLayout;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    
    View view = inflater.inflate(R.layout.<your fragment xml>, container, false);

    linearLayout= view.findViewById(R.id.linearLayout);
    ...
    return view;
}

然后,在onViewCreated中,您需要使用以下代码:

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {

    linearLayout.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view12) {
            try {
                InputMethodManager inputMethodManager = (InputMethodManager) Objects.requireNonNull(VideoFragment.this.getActivity()).getSystemService(INPUT_METHOD_SERVICE);
                assert inputMethodManager != null;
                inputMethodManager.hideSoftInputFromWindow(VideoFragment.this.getActivity().getCurrentFocus().getWindowToken(), 0);

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });

}

0

我已经完成了所有步骤,但似乎还有些东西不对。我使用了那种方法在片段中隐藏了键盘。

fun hideKeyBoard(view: View) {
        val inputManager =
            requireActivity().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
        inputManager.hideSoftInputFromWindow(
            view.windowToken,
            SOFT_INPUT_STATE_ALWAYS_HIDDEN
        )
    }

但是当我打开片段时,键盘也会自动打开,经过很多搜索后,我发现问题出在我必须将这些代码放在我的xml布局根目录中。

android:focusable="true"
android:focusableInTouchMode="true" 

注意:如果您删除上述方法,只需将属性放置在根布局中,它将正常工作。

0

只需在您的代码中添加这一行:

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

0

使用这个:

Button loginBtn = view.findViewById(R.id.loginBtn);
loginBtn.setOnClickListener(new View.OnClickListener() {
   public void onClick(View v) {
      InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(getActivity().INPUT_METHOD_SERVICE);
      imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
   }
});

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