Android处理软键盘弹出问题和键盘表情切换问题

软键盘可能引发的问题:

  1. 键盘弹出,可能会挤压页面中的布局和view,导致页面显示不可控,尤其是当页面设置了各种主题的时候,更加不可控制;
  2. 处理软键盘和表情键盘切换,很容易造成切换生硬,有闪烁的问题;

 

传统解决方案的缺陷:

网上有很多解决方案,大多都是设置 android:windowSoftInputMode="adjustResize|stateHidden",并把输入框靠近底部,这样就能通过窗口自适应把相应的输入控件挤上去,而且可以通过布局变化监听到软键盘弹出和消失事件,方便处理回调;

关于更多windowSoftInputMode等设置,请自行百度;

但是本人通过上述方法试过之后,发现有以下缺陷:

  1. 设置了adjustResize,不只会影响输入控件,是对布局中所有控件都有影响,比如说一张自适应图片,就可能会被挤压变形;而且如果有表情键盘的情况下,表情键盘也会被挤压上去,切换时只能将表情键盘设置为不可见,这样就会造成切换闪烁问题;
  2. 页面嵌套设置主题影响: 如果当前页面嵌套在其他页面中,或者其他页面嵌套当前页面, 如果在外层或内层由于需求代码手动修改了键盘弹出模式,那么键盘弹出的表现将会出现不可控的情况;
  3. 如果多个页面都要用到输入控件,那么需要在每个页面中增加适配代码,与页面耦合严重,不利于封装;

 

新的解决方式:

我门在项目里使用了一种新方案,解决了上述问题; 大致方案如下:

第一步: 把输入控件抽离到单独的activity中;

为了解决由于外层页面影响键盘模式, 我门把输入控件放到单独的activity里面,当然,这个activity是透明的,他的主题设置为:

 <style name="inputStyle" parent="UiKit.Light.Translucent">
        <item name="android:statusBarColor">@android:color/transparent</item>
        <!-- 半透明 -->
        <item name="android:windowIsTranslucent">true</item>
        <!-- 无标题 -->
        <item name="android:windowNoTitle">true</item>
        <!-- 背景透明 -->
        <item name="android:windowBackground">@android:color/transparent</item>
    </style>

同时,我们设置 android:windowSoftInputMode="adjustNothing",这样固定页面中所有元素,不会跟随软件盘弹起,后面我们自己设置键盘的高度; 里面有点击空白消失的逻辑以及发送消息后的回调等等,那些就自己处理吧;

 

第二步: 监听键盘弹出;

由于我们设置了键盘弹出模式为adjustNothing,所以传统的监听布局变化的代码不会被触发,即 decorView?.viewTreeObserver?.addOnGlobalLayoutListener(mGlobalLayoutListener)中的listener不会被调用, 我们需要一个新的方法来监听, 思路是开启一个看不见的popupWIndow,宽度为0,高度为MATCH_PARENT,通过它的

OnGlobalLayoutListener来监听.工具类代码如下:
class SoftKeyboardHeightProvider : PopupWindow, ViewTreeObserver.OnGlobalLayoutListener {

    var rootView: View? = null
    var mActivity: Activity? = null
    var heightMax: Int = 0
    var listener: KeyboardListener? = null
    var lastKeyboardHeight = -1
    var isFirstLayout = true

    constructor(context: Activity) : super(context) {
        mActivity = context
        rootView = View(context)
        contentView = rootView
        rootView?.viewTreeObserver?.addOnGlobalLayoutListener(this)

        //设置宽度为0,高度为全屏
        width = 0
        height = ViewGroup.LayoutParams.MATCH_PARENT

        //设置键盘弹出方式
        softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
        inputMethodMode = PopupWindow.INPUT_METHOD_NEEDED
    }

    fun init() {
        if (!isShowing) {
            var decorView = mActivity?.window?.decorView ?: return
            decorView.post {
                showAtLocation(decorView, Gravity.NO_GRAVITY, 0, 0)
            }
        }
    }

    override fun onGlobalLayout() {
        var rect = Rect()
        rootView?.getWindowVisibleDisplayFrame(rect)
        if (rect.bottom > heightMax) {
            heightMax = rect.bottom
        }
        var keyboardHeight = heightMax - rect.bottom
        if (listener != null && keyboardHeight != lastKeyboardHeight && !isFirstLayout) {
            listener?.onHeightChanged(keyboardHeight)
        }
        lastKeyboardHeight = keyboardHeight
        isFirstLayout = false

    }

    interface KeyboardListener {
        fun onHeightChanged(heigt: Int)
    }
}

使用如下:

 var provider = SoftKeyboardHeightProvider(this)
        provider.init()
        provider.listener = object : SoftKeyboardHeightProvider.KeyboardListener {
            override fun onHeightChanged(heigt: Int) {
                // 键盘高度变化
            }
        }

 

第三步: 处理表情和键盘切换

这里每一种实现的控件可能有所不同,但是要保证表情和键盘切换顺滑,有几个要点:

1.保证表情和键盘高度一样,这个可以在第一次显示软键盘时记录高度,并设置给表情键盘; 如果首次显示表情键盘,此时软键盘高度未获取,那么此时可以高度不一致;

2.切换软键盘时表情键盘不做消失处理,只让软键盘覆盖住表情键盘;即表情键盘始终存在;

 

最终完成后的demo效果如下:

demo效果

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

龍林1102

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值