• Android开发 在用EditText对话框Dialog退出后实现输入盘的退出


    前言

      在使用继承的Dialog的方式实现自定义Dialog,如果这个Dialog我们还添加了EditText就会发现一个问题。在输入盘显示后,Dialog退出输入盘不会退出。网上有一些奇怪的解决办法,最奇怪的是去根据Touch事件判断Touch坐标来确定是否点击了空白在隐藏输入盘,绕了一个大圈来实现,根本就没仔细阅读过Dialog的代码。其实实现退出Dialog的时候隐藏输入法很简单,只要重写Dialog的dismiss()方法即可,为什么写这篇博客是因为不想大家被错误的实现方式而误导。所以,这里会啰嗦下问题根结。

    了解Dialog的退出方式

      在了解隐藏输入盘之前,需要排列一下Dialog的退出的3种方式:

      1.自定义退出按键,点击后实现dialog.dismiss(); 退出对话框

      2.按back键,退出对话框

      3.点击Dialog外面的空白背景,退出对话框

    错误的隐藏输入盘的方式

                @Override
                public void onClickLeft(EditDialog dialog) {
                    dialog.dismiss();
                    InputMethodManager imm = (InputMethodManager) dialog.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
                    imm.hideSoftInputFromWindow(dialog.getEditContent().getWindowToken(), InputMethodManager.RESULT_UNCHANGED_SHOWN);
                }

    说说为什么这种方式有问题,其实是因为你调用了dialog.dismiss(); 后在获取dialog.getEditContent().getWindowToken() 这个token的时候,必定会返回为null。 因为你的Dialog已经退出了。这个EditText已经被Window解除关系。所以我们需要在dimiss方法之前隐藏输入盘。

    容易被误导难点在哪里?

     看了上面的错误例子,我们肯定会在隐藏输入法后在调用dismiss(); 好像问题已经解决了? 并没有,因为你只解决了第一种情况 ”自定义退出按键,点击后实现dialog.dismiss(); 退出对话框“ ,还有

    按back键,退出对话框“ 

    点击Dialog外面的空白背景,退出对话框

    这2个情况的调用是Dialog直接在内部封装调用了dismiss(); 你无法在获取在dismiss之前操作隐藏输入盘。 setOnDismissListener();方法 与 setOnCancelListener();方法 都是执行完dismiss();方法后调用的。这里下面的源码中看到

    按外部空白退出的方式

        /**
         * Called when a touch screen event was not handled by any of the views
         * under it. This is most useful to process touch events that happen outside
         * of your window bounds, where there is no view to receive it.
         * 
         * @param event The touch screen event being processed.
         * @return Return true if you have consumed the event, false if you haven't.
         *         The default implementation will cancel the dialog when a touch
         *         happens outside of the window bounds.
         */
        public boolean onTouchEvent(@NonNull MotionEvent event) {
            if (mCancelable && mShowing && mWindow.shouldCloseOnTouch(mContext, event)) {
                cancel();
                return true;
            }
            
            return false;
        }

    按返回键退出的方式

        /**
         * Called when the dialog has detected the user's press of the back
         * key.  The default implementation simply cancels the dialog (only if
         * it is cancelable), but you can override this to do whatever you want.
         */
        public void onBackPressed() {
            if (mCancelable) {
                cancel();
            }
        }

    最后都调用了cancel()方法,而cancel方法最后都调用了dismiss方法,但是这些回调都是用Handler发出去的,所以Dialog都已经关闭(并没有被销毁)与window解除了绑定关系了,才会接收到 setOnDismissListener();方法 与 setOnCancelListener(); 这2个回调。所以在这2个回调里写隐藏输入盘也是错误的。

    正确的方式

    重写dismiss方法

        @Override
        public void dismiss() {
            InputMethodManager imm = (InputMethodManager) mEditContent.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
            imm.hideSoftInputFromWindow(mEditContent.getWindowToken(), InputMethodManager.RESULT_UNCHANGED_SHOWN);
            super.dismiss();
        }

    End

  • 相关阅读:
    蓝牙学习(5) -- sockets
    蓝牙学习(4) -- L2CAP
    蓝牙学习(3) Linux kernel部分Bluetooth HCI分析
    蓝牙学习(2)USB Adapter
    蓝牙bluez学习(1) Stack Architecture
    Release Python Program as exe
    蓝牙stack bluez学习(1)Stack Architecture
    树莓派
    树莓派
    关于Reflow回流
  • 原文地址:https://www.cnblogs.com/guanxinjing/p/12980640.html
Copyright © 2020-2023  润新知