判断dialog或者view 是否被键盘遮挡

项目场景:

最近在项目开发中,遇到一个兼容性的问题。在Fragment 中 从底部弹出一个 继承 DialogFragment 的自定义Dialog ,布局里面有 EditText , 弹出 dialog 后,EditText 获取焦点,弹出键盘后,dialog 没有被顶上去,而是完完全全的被键盘遮挡住了。
在特定机型:ViVo Y9/Y50 上面复现。


问题描述

一开始的代码如下:

 override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        dialog?.window?.apply {
            setWindowAnimations(R.style.base_dialog_bottom_anim)
            setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE or WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN)
        }
        
	   // 省略view 实例化代码
      
      // 延迟300 ms主动弹出键盘
        Handler(Looper.getMainLooper()).postDelayed({
            SoftKeyboardUtil.openKeyBoard(binding.editName)
        }, 300)
    }

对于键盘遮挡布局的问题,网上大部分的方案都是设置 setSoftInputMode
无论是在 Manifest 中给 Activity 设置 android:windowSoftInputMode="adjustResize|adjustPan"
还是通过代码设置:getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE | WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN)

对于这些方案,笔者都尝试过,对于大部分的手机都是有效的。但是仅仅对于ViVo 部分手机无效。
兼容性的问题很是让人蛋疼…


原因分析:

笔者尝试过好几种方案,当键盘弹出来的时候,手动改变 弹出的 dialog 的显示位置。
1、比对 键盘弹出前 和弹出后, dialog?.window?.layoutParams 中的 坐标 y 的位置;结果:失败。因为无论是正常手机还是有兼容性的手机,无论是dialog 被 键盘顶上去 还是被遮挡, y 的值始终是0.
2、…


解决方案:

最后的解决办法是,因为手机屏幕是固定的,宽高也是固定的。而 dialog 布局显示的位置 是不固定的。
画一个粗糙的图展示下:

在这里插入图片描述

当有兼容性的手机无论是弹出键盘还是不弹出键盘,其 在屏幕中 的坐标 y 始终是 0 ,而对于正常的 手机 不弹出键盘 其坐标 y 为0 ,弹出键盘 其在屏幕中的坐标则是 location[1] 。
所以我们可以通过 dialog 的布局在屏幕中的位置也判断 当前dialog 是否被键盘遮挡还是正常顶起来。然后通过动态的修改 dialog 的 LayoutParam 的 坐标 y 来改变dialog 的位置,从而能让dialog 不至于被键盘遮挡。

修改后的代码如下:

 override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        dialog?.window?.apply {
            setWindowAnimations(R.style.base_dialog_bottom_anim)
            setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE or WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN)
        }
		// 获取整个 window 的高度
        requireActivity().window?.apply {
            windowHeight = decorView.rootView.height
        }
		// 设置键盘 弹起与关闭 的监听
        globalListener =
            SoftKeyboardUtil.setOnKeyboardListener(requireActivity(), object : SoftKeyboardUtil.OnKeyboardStateChangedListener {
                override fun onKeyBoardShow(boardHeight: Int) {

                    val intArray = IntArray(2)
                    // 获取dialog 的根布局在 屏幕中的位置
                    binding.root.getLocationOnScreen(intArray)
					// 如果是正常手机,则 intArray[1] + contentHeight 的和一定小于 屏幕的高度,没有被键盘弹起的一定是大于等于。看图...
                    if (intArray[1] + contentHeight >= windowHeight) {
                    // 如果 dialog 被遮挡了,手动把dialog 移动到键盘上面位置
                        dialog?.window?.updateLayoutParams {
                            y = boardHeight
                        }
                    }
                }

                override fun onKeyBoardHide() {
                // 键盘关闭,则 把 dialog 移动到底部。
                    dialog?.window?.updateLayoutParams {
                        y = 0
                        x = 0
                    }
                }
            })

        Handler(Looper.getMainLooper()).postDelayed({
        // 获取 dialog 布局的高度。
            contentHeight= binding.root.measuredHeight
            SoftKeyboardUtil.openKeyBoard(binding.editName)
        }, 300)
    }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值