如何通过仅一次点击EditText外部来隐藏键盘?

8
我希望你能够通过在EditText外部轻击来隐藏键盘。这是我的XML代码:
<RelativeLayout
android:clickable="true"
android:focusable="true"
android:focusableInTouchMode="true"
android:onClick="rl_main_onClick">
<RelativeLayout
  //Here there are some widgets including some edittext.
</RelativeLayout>

这是我的Java代码(MainActivity):
public void rl_main_onClick(View view) {
    InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
}

但是我必须点击两次才能隐藏键盘。第一次点击只会将“下一个”(对于最后一个编辑文本框,它会变成“完成”)更改为“输入”图标,然后第二次点击才会隐藏键盘。

这是第一次点击发生的情况:

第一次点击所做的事情。

现在我有两个问题:

  1. 如何修复它并通过一次点击隐藏键盘?

  2. 是否可以为所有编辑文本框都做到这一点(一个代码适用于所有)?

9个回答

18

尝试用 onTouch 替换 onClick。为此,您需要更改布局属性,如下所示:

<RelativeLayout
    android:id="@+id/relativeLayout"
    android:clickable="true"
    android:focusable="true"
    android:focusableInTouchMode="true">

    <RelativeLayout>

        // widgets here

    </RelativeLayout>

</RelativeLayout>

然后删除rl_main_onClick(View view) {...}方法,并在onCreate()中插入onTouch监听器方法:

findViewById(R.id.relativeLayout).setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
        return true;
    }
});

3
我使用以下过程。它完美地为我工作。在您的活动类中添加以下函数即可。

我使用以下流程。它对我非常有效。在您的活动类中添加以下功能。

  override fun dispatchTouchEvent(event: MotionEvent): Boolean {
if (event.action == MotionEvent.ACTION_DOWN) {
    val v = currentFocus
    if (v is EditText) {
        val outRect = Rect()
        v.getGlobalVisibleRect(outRect)
        if (!outRect.contains(event.rawX.toInt(), event.rawY.toInt())) {
            Log.d("focus", "touchevent")
            v.clearFocus()
            val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
            imm.hideSoftInputFromWindow(v.windowToken, 0)
        }
    }
}
return super.dispatchTouchEvent(event)}

您可以使用以下代码检查Focus状态。适用于activity和Fragment。
appCompatEditText.onFocusChangeListener = View.OnFocusChangeListener { view, hasFocus ->
            if (!hasFocus) {
                toast("Focus Off")
            }else {
                toast("Focus On")
            }
        }

2
非常干净。我在 Kotlin 中尝试了一下,运行正常。 - David Felipe Medina Mayorga

2
Kotlin版本与扩展
fun View.hideKeyboard() {
    val inputMethodManager = context!!.getSystemService(android.content.Context.INPUT_METHOD_SERVICE) as? InputMethodManager
    inputMethodManager?.hideSoftInputFromWindow(this.windowToken, 0)
}

然后从碎片中这样调用它

view.setOnClickListener {
    it.hideKeyboard()
}

或者像这样从活动中,contentView是我的根视图的ID

val contentView: View = findViewById(R.id.contentView)
    contentView.setOnClickListener {
    it.hideKeyboard()
}

1

不必遍历所有视图或覆盖dispatchTouchEvent。

为什么不直接重写Activity的onUserInteraction()方法,这将确保在用户点击Editext之外时键盘消失。

即使Editext位于scrollView中,也可以使用。

@Override
public void onUserInteraction() {
    if (getCurrentFocus() != null) {
        InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
    }
    super.onUserInteraction()
}

@SKG,你只是忘了调用super。否则,交互将不起作用。 super.onUserInteraction() - Shohan Ahmed Sijan

0
override fun onUserInteraction() {
    if (currentFocus != null) {
        val imm: InputMethodManager = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
        imm.hideSoftInputFromWindow(currentFocus!!.windowToken, 0)

这个有效,但是当我按键盘输入时,它也被隐藏了。


0

完美运行且干净的解决方案:

override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
    currentFocus?.let {
        val imm: InputMethodManager = getSystemService(
            Context.INPUT_METHOD_SERVICE
        ) as (InputMethodManager)
        imm.hideSoftInputFromWindow(it.windowToken, 0)
    }
    return super.dispatchTouchEvent(ev)
}

0

不确定是否有帮助,我做了类似于片段的东西。它们在activity_main xml中的容器(FrameLayouts)内。

首先,我将此添加到父片段布局中:

android:id="@+id/fragment_layout"
android:clickable="true"
android:focusableInTouchMode="true"
android:focusable="true"

然后我声明并初始化布局:

ConstraintLayout constraintLayout;

在onCreateView方法中:

constraintLayout = ppm.findViewById(R.id.fragment_layout);
constraintLayout.setOnFocusChangeListener(onFocusChangeListener);

这里是onFocusChangeListener:

View.OnFocusChangeListener onFocusChangeListener = new View.OnFocusChangeListener() {
    @Override
    public void onFocusChange(View v, boolean hasFocus) {

        if (hasFocus) {
            InputMethodManager imm = (InputMethodManager) Objects.requireNonNull(Objects.requireNonNull(getContext()).getSystemService(Context.INPUT_METHOD_SERVICE));
            imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
        }

    }
};

0

将以下属性添加到布局文件的顶部布局中,以通过轻触TextField外部来清除焦点。

<androidx.constraintlayout.widget.ConstraintLayout 
    android:clickable="true"
    android:focusable="true"
    android:focusableInTouchMode="true"

对于Fragment。 在OnFocusChangeListener中添加以下代码,通过点击TextField外部来隐藏键盘。 我将在接口中定义它,并在具体类中实现它。
public interface CommonFragment {

    FragmentActivity fragmentActivity();

    default View.OnFocusChangeListener hideKeyboardListener() {
        return (view, b) -> {
            if (b) {
                InputMethodManager inputManager = (InputMethodManager) fragmentActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
                inputManager.hideSoftInputFromWindow(view.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
            }
        };
    }
}

public MyFragment extends Fragment implements CommonFragment {

    @Override
    public FragmentActivity fragmentActivity() {
        return requireActivity();
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        // "binding.container" is top layout by View Biding 
        binding.container.setOnFocusChangeListener(hideKeyboardListener());
    }
}

0
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    if (getCurrentFocus() != null) {
        InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
    }
    return super.dispatchTouchEvent(ev);
}

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