美文网首页
Activity界面销毁 软键盘未收回

Activity界面销毁 软键盘未收回

作者: 小笨_ee05 | 来源:发表于2019-12-10 17:00 被阅读0次

    在项目开发过程中,界面包含EditText输入框时,输入内容时软键盘弹起。但是此时我们调用界面中自定义的返回按钮执行.finish()方法销毁Activity后发现软键盘并没有跟随关闭收回,参考了网上各种方法后,试验总结出自己项目中可用的方案。

    注意:此篇记录的是调用.finish()返回时软键盘未回收问题,而非手机本身的back键(手机本身的back键点击是会先收回软键盘,在销毁Activity)。

    1、在AndroidManifest.java清单文件的<activity />标签下加入stateUnspecified。

    使用环境是在ActivityB开启ActivityC,ActivityC中包含EditText,点击输入框获取焦点使软键盘弹出,然后调用自定义返回按钮执行.finish()方法,当ActivityC销毁后返回到ActivityB界面时,软键盘未回收问题,此时可以在AndroidManifest.java的ActivityB的标签下添加android:windowSoftInputMode="stateUnspecified"。

    原文链接:Activity退出后,键盘不收回

    注:此方案在我的项目中使用无效,在此记录。

    B界面设置android:windowSoftInputMode 键盘是否自动回收
    stateUnspecified
    stateUnchanged
    stateHidden
    stateAlwaysHidden
    stateVisible
    stateAlwaysVisible
    stateHidden
    不指定
    2、在Activity的onDestory方法中监测软键盘是否存在,存在则回收。

    备注:此方法不稳定,在Activity中不包含EditText时会莫名其妙的弹起软键盘。

        @Override
        protected void onDestroy() {
            super.onDestroy();
            InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
            if (imm != null) {
                imm.hideSoftInputFromWindow(getWindow().getDecorView().getWindowToken(), 0);
            }
        }
    
    3、在.finish()前先收回软键盘

    在每个Activity中调用.finish()前手动调用收回软键盘方法,此方案测试过几个页面,可以使用。在使用时最好判断软键盘是否有显示,若显示则回收,否则忽略。

        @OnClick({R.id.iv_back)
        void iv_depart_back(View view){
            hideInput()
            finish();
        }
        protected void hideInput() {
            super.onDestroy();
            InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
            if (imm != null) {
                imm.hideSoftInputFromWindow(getWindow().getDecorView().getWindowToken(), 0);
            }
        }
    
    4、自定义View,覆写dispatchKeyEventPreIme(KeyEvent event)方法

    此方案未测试,针对现有的项目不好再去改动之前已经定义好的View内容,所以是新开启项目的可以尝试使用。

    import android.app.Activity;
    import android.content.Context;
    import android.util.AttributeSet;
    import android.view.KeyEvent;
    import android.view.inputmethod.InputMethodManager;
    import android.widget.RelativeLayout;
    /**
     * Finishes the containing activity on BACK, even if input method is showing.
     */
    public class SearchActivityView extends RelativeLayout {
        public SearchActivityView(Context context) {
            super(context);
        }
        public SearchActivityView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
        public SearchActivityView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
        }
        private Activity getActivity() {
            Context context = getContext();
            if (context instanceof Activity) {
                return (Activity) context;
            } else {
                return null;
            }
        }
        /**
         * Hides the input method.
         */
        protected void hideInputMethod() {
            InputMethodManager imm = (InputMethodManager)getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
            if (imm != null) {
                imm.hideSoftInputFromWindow(getWindowToken(), 0);
            }
        }
        /**
         * Overrides the handling of the back key to dismiss the activity.
         */
        @Override
        public boolean dispatchKeyEventPreIme(KeyEvent event) {
            Activity activity = getActivity();
            if (activity != null && event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
                KeyEvent.DispatcherState state = getKeyDispatcherState();
                if (state != null) {
                    if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
                        state.startTracking(event, this);
                        return true;
                    } else if (event.getAction() == KeyEvent.ACTION_UP && !event.isCanceled() && state.isTracking(event)) {
                        hideInputMethod();
                        activity.onBackPressed();
                        return true;
                    }
                }
            }
            return super.dispatchKeyEventPreIme(event);
        }
    }
    

    原文链接:https://blog.csdn.net/twoicewoo/article/details/7385876

    5、设置自定义的返回按钮响应系统的back键,在点击事件中执行

    此方式需要在线程中执行,未进行测试。

    new Thread () {
        public void run () {
            try {
                Instrumentation inst= new Instrumentation();
                inst.sendKeyDownUpSync(KeyEvent. KEYCODE_BACK);
            } catch(Exception e) {
                e.printStackTrace();
            }
        }
    }.start();
    

    原文链接:https://blog.csdn.net/qq_36487432/article/details/82226125

    6、最终解决方案(方案3改良版本)

    方案3中的方式可以用,但是有弊端,需要每个Activity中单独添加,如果之前在Base基类中定义过统一的关闭方式修改还是比较方便的。但是如果没有,也没关系。我们可以在Base基类中覆写finisi()方法,来关闭软键盘。

    @Override
    public void finish() {
        super.finish();
        hideKeyBoard();
    }
    /**
    * 关闭软键盘
    */
    public void hideKeyBoard() {
        InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
        if(imm.isActive()&&getCurrentFocus()!=null){
            if (getCurrentFocus().getWindowToken()!=null) {
                 imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
            }
        }
     }
    
    总结:上述方案1、2、3都测试过,在不同机型上使用效果都有差异,最后的方案6在现有的测试机上测试都可以正常显示和关闭,在此进行记录。

    相关文章

      网友评论

          本文标题:Activity界面销毁 软键盘未收回

          本文链接:https://www.haomeiwen.com/subject/josggctx.html