失去焦点时隐藏软键盘

51

当我们有一个 EditText 并且它失去焦点时(转移到不需要键盘的元素),软键盘应该自动隐藏还是我们应该自己隐藏它?

我将焦点从一个 AutoCompleteSearchView(我猜应该像 EditText 一样)移动到一个 ButtonrequestFocus() 返回 true,但键盘并没有隐藏。


8
我有这方面的疑问,所以才在询问。 - fweigl
@Ascorbin 不要搞砸了,安卓会处理这个问题的。 - Pragnani
6
是啊,但在我的情况下并不适用。 - fweigl
1
你在问他是否尝试做某事,而你刚刚说它应该自动完成吗? - Mukherjee
10个回答

72

最好的方法是为EditText设置一个OnFocusChangeListener,然后将代码添加到监听器的OnFocusChange方法中来处理键盘。当EditText失去焦点时,Android会自动关闭键盘。

在你的OnCreate方法中可以这样写:

EditText editText = (EditText) findViewById(R.id.textbox);
OnFocusChangeListener ofcListener = new MyFocusChangeListener();
editText.setOnFocusChangeListener(ofcListener);

然后添加类:

private class MyFocusChangeListener implements OnFocusChangeListener {

    public void onFocusChange(View v, boolean hasFocus){

        if(v.getId() == R.id.textbox && !hasFocus) {

            InputMethodManager imm =  (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
            imm.hideSoftInputFromWindow(v.getWindowToken(), 0);

        }
    }
}

19
那么这个操作需要针对应用程序中的每个editText组件都进行一遍?难道没有全局设置来定义这种行为吗?如果没有,而且应用程序中有很多editTexts,我建议扩展editText类,将监听器添加到扩展类中,并在整个应用程序中使用修改后的类。 - GyRo
13
如何让其自动化?如果我有150份通过25的表格,我不想每次都手动操作... 这个功能应该很明显。 - Loenix
1
我不得不在根视图(片段中)添加以下内容: rootView.setFocusable(true); rootView.setFocusableInTouchMode(true); rootView.setClickable(true); - beee

9

Android不会为您隐藏键盘。如果您希望在EditText失去焦点时隐藏键盘,请尝试在该事件上使用类似于以下方法:

private void hideKeypad() {
    EditText edtView = (EditText) findViewById(R.id.e_id);

    InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(edtView.getWindowToken(), 0);
}

7

试试这个

 /**
 * Hide keyboard on touch of UI
 */
public void hideKeyboard(View view) {

    if (view instanceof ViewGroup) {

        for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {

            View innerView = ((ViewGroup) view).getChildAt(i);

            hideKeyboard(innerView);
        }
    }
    if (!(view instanceof EditText)) {

        view.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                hideSoftKeyboard(v);
                return false;
            }

        });
    }

}

/**
 * Hide keyboard while focus is moved
 */
public void hideSoftKeyboard(View view) {
    if (view != null) {
        InputMethodManager inputManager = (InputMethodManager) contentsContext_
                .getSystemService(Context.INPUT_METHOD_SERVICE);
        if (inputManager != null) {
            if (android.os.Build.VERSION.SDK_INT < 11) {
                inputManager.hideSoftInputFromWindow(view.getWindowToken(),
                        0);
            } else {
                if (this.getCurrentFocus() != null) {
                    inputManager.hideSoftInputFromWindow(this
                            .getCurrentFocus().getWindowToken(),
                            InputMethodManager.HIDE_NOT_ALWAYS);
                }
                view.clearFocus();
            }
            view.clearFocus();
        }
    }
}

5

试试这个,也许能解决你的问题。

private void hideKeyboard() {
    InputMethodManager mImMan = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
    mImMan.hideSoftInputFromWindow(mYourEdttxtName.getWindowToken(), 0);
}

您可以从这里找到更多信息。

你救了我的命!我只是复制了它,它就能用了! - acmpo6ou

4
您可以重写dispatchTouchEvent方法来实现它:
@Override
public boolean dispatchTouchEvent(MotionEvent event) {

    if (event.getAction() == MotionEvent.ACTION_DOWN) {

        /**
         * It gets into the above IF-BLOCK if anywhere the screen is touched.
         */

        View v = getCurrentFocus();
        if ( v instanceof EditText) {


            /**
             * Now, it gets into the above IF-BLOCK if an EditText is already in focus, and you tap somewhere else
             * to take the focus away from that particular EditText. It could have 2 cases after tapping:
             * 1. No EditText has focus
             * 2. Focus is just shifted to the other EditText
             */

            Rect outRect = new Rect();
            v.getGlobalVisibleRect(outRect);
            if (!outRect.contains((int)event.getRawX(), (int)event.getRawY())) {
                v.clearFocus();
                InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
            }
        }
    }
    return super.dispatchTouchEvent( event );
}

额外奖励: 如果一个EditText获得焦点,触发的事件顺序是:

  1. 如果另一个EditText失去焦点,则调用另一个EditText的onFocusChange()
  2. 调用ACTION_DOWN方法
  3. 最后,将调用该EditText的onFocusChange()方法。

2
只需创建一个静态方法。
public static void touchScreenAndHideKeyboardOnFocus(View view, final Activity activity) {

    if (view instanceof EditText) {
        view.setOnFocusChangeListener(new View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(View v, boolean hasFocus) {
                if (!hasFocus) {
                    if(activity != null) {
                       InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
                       if (activity.getCurrentFocus() != null) {
                          inputMethodManager.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
                       }
                    }
                }
            }
        });
    }

    if (view instanceof ViewGroup) {
        for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
            View innerView = ((ViewGroup) view).getChildAt(i);
            touchScreenAndHideKeyboardOnFocus(innerView, activity);
        }
    }
}

视图是您布局的根视图..但要小心,如果您的EditText中有另一个焦点侦听器..


什么是“forcely”? - Hatim

2
这个问题的解决方案已经在这里找到:这里
它在activity上使用DispatchTouchEvent,而不是将每个EditText钩子连接到FocusChange或Touch事件。
这是一个更好的解决方案。

我的Xamarin实现如下:

public override bool DispatchTouchEvent(MotionEvent ev)
    {
        if (ev.Action == MotionEventActions.Down)
        {
            var text = CurrentFocus as EditText;
            if (text != null)
            {
                var outRect = new Rect();
                text.GetGlobalVisibleRect(outRect);
                if (outRect.Contains((int) ev.RawX, (int) ev.RawY)) return base.DispatchTouchEvent(ev);
                text.ClearFocus();
                HideSoftKeyboard();
            }
        }
        return base.DispatchTouchEvent(ev);
    }

protected void HideSoftKeyboard()
    {
        var inputMethodManager = (InputMethodManager) GetSystemService(InputMethodService);
        inputMethodManager.HideSoftInputFromWindow(CurrentFocus.WindowToken, 0);
    }

2
这个方法对我有效:
InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0);

1

我想为答案集合添加一个Kotlin简化版本:

// onCreateView of the Fragment
myAutocompleteText.apply {
    setAdapter(adapter) // whatever the adapter is
    setOnFocusChangeListener { _, hasFocus ->
        if (hasFocus) requireActivity().closeKeyboard() // if called from an Activity instead of a Fragment, just replace it's reference instead of requireActivity()
    }
}


/**
 * Hides the keyboard if possible.
 */
object KeyboardUtils {
    fun Activity.hideKeyboard() {
        if (currentFocus != null) {
            (getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager)?.hideSoftInputFromWindow(currentFocus!!.windowToken, 0)
        }
    }
}

0

我的问题通过这段代码得到了解决(在Fragment中)

LinearLayout linearLayoutApply=(LinearLayout)rootView.findViewById(id.LinearLayoutApply);

    linearLayoutApply.setOnFocusChangeListener(new View.OnFocusChangeListener() {
        @Override
        public void onFocusChange(View v, boolean hasFocus) {
            if(hasFocus)
            {
                hideKeyBoard(v);
            }
        }
    });

隐藏键盘

 public void hideKeyBoard(View v)
{
    InputMethodManager imm=(InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(getActivity().getCurrentFocus().getWindowToken(), 0);
}

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