最近项目需求,点击弹窗以外区域先判断软键盘是否隐藏,如果软键盘显示,则先隐藏软键盘,否则直接退出弹窗。为此查了好多资料,发现对于软键盘是否显示并无对应的接口,网上也有篇文章对各种方法进行了测试,我也测试过确实没什么用。参考:判断软键盘是否显示的各种方法测试结果 对于以上文章当中有一种判断方法,可以采用,但是不是很通用。1.需要根据屏幕中软键盘的高度确定以下2/3这个值,对于有横竖屏软键盘高度不一,就不好定了,还要判断横竖屏状态,标题栏的高度改变了对这个比例值可能也有影响。2.rect.bottom这个参数获取的值,我还没整明白,各种情况下获取的值都不一定是可视区域的bottom值。(因为项目很赶,当时没来得及记录具体情况)
参考资料

/**
     *判断输入法是否显示
     * @return
     */
    private boolean isSoftShowing() {
        //获取当前屏幕内容的高度
        int screenHeight = getWindow().getDecorView().getHeight();
        //获取View可见区域的bottom
        Rect rect = new Rect();
        getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);

        return screenHeight * 2 / 3 > rect.bottom;
    }

具体原理解析如下:
Android获取窗口可视区域大小: getWindowVisibleDisplayFrame()

于是想了好久,绝对另辟蹊径了!!!希望可以给大家一点提示啦哈~(此方法只对软键盘弹出时会将控件顶上去的方式有用)
既然如此就好办了,以含编辑框的弹窗为例。
在弹窗的onCreate()方法里面,创建编辑框EditText时,使用view.post或view.postDelayed记录绘制View时编辑框的Y坐标。每次点击弹窗区域以外区域判断一下编辑框的Y坐标是否等于原始坐标,以此判断软键盘是否弹出。

【注意:如果直接在onCreate()里获取编辑框的坐标值会为0,因为控件没有绘制完成,还没有attach到window上,所以获取的坐标值为0,具体解决方案一般是用view.post或者view.postDelayed来解决。具体解析可参考超详细!!Android View.post和View.postDelayed view.post是主线程执行完成后立刻调用,view.postDelayed相当于定时器,主线程执行完后延迟多少秒调用。】

事不宜迟,开干咯~

主要的代码如下:

//记录editText的原始Y坐标
editText.post(new Runnable() {
            @Override
            public void run() {
                //获取editText的Y坐标
                int[] location=new int[2];
                editText.getLocationOnScreen(location);
                int positionY=location[1];
                //记录初始位置
                posY=positionY;
                android.util.Log.d(TAG, "初始位置--- "+positionY);//posY===902(坐标原点是左上角哦~~~)

            }
        });
//弹窗点击事件 
  @Override
    public boolean onTouchEvent( MotionEvent event) {
        switch (event.getAction()){
        //MotionEvent
            case MotionEvent.ACTION_DOWN:
            //判断点击区域是否为弹窗区域以外
                if (isOutOfBounds(getContext(),event)){
                    //获取当前控件的Y坐标
                    int[] location=new int[2];
                    editText.getLocationOnScreen(location);
                    int positionY=location[1];
                    Log.d(TAG, "onTouchEvent: 当前位置---"+positionY);//positionY===503(软键盘弹出后的位置)
                    if (posY!=positionY){
                        final InputMethodManager imm = (InputMethodManager)mContext.
                                getSystemService(Context.INPUT_METHOD_SERVICE);
                        imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);//软键盘隐藏
                        editText.clearFocus();//取消光标焦点
                        Log.d(TAG, "onTouchEvent: 点击区域外部软键盘隐藏");
                    }else {
                        Log.d(TAG, "onTouchEvent: 退出");
                        dismiss();
                    }
                }
                break;
        }
        return false;

    }
/**
     * 判断点击区域是否在弹窗区域外
     * @param context
     * @param event
     * @return
     */
    public boolean isOutOfBounds(Context context, MotionEvent event) {
        final int x = (int) event.getX();
        final int y = (int) event.getY();
        final int slop = ViewConfiguration.get(context).getScaledWindowTouchSlop();
        final View decorView = getWindow().getDecorView();
        return (x < -slop) || (y < -slop) || (x > (decorView.getWidth() + slop))
                || (y > (decorView.getHeight() + slop));
    }