Android软键盘遮挡按钮的优雅解决方案
2023-02-23 本文已影响0人
寻水的鱼Chock
关于这个问题网上有很多的资料,大部分都是去修改windowSoftInputMode这个属性,诚然部分情况下它是有效的,它无非就是可选的两种情况:
- 整个窗口布局不变,软件盘弹出完全遮挡底部UI;
- 整个窗口整体向上滑移,完全露出整个窗口UI。
可以预见,它们并不适用所有的情况,模式1)好理解,是完全不可接受,模式2)在按钮底部还存在较大空间时,整体向上“顶”并不美观,同时顶部的部分UI同样会面临再次被遮挡的问题,所以它不是很完美。那有没有一种折中的方法呢?有。如果我们能够检测到软键盘弹出,接着计算出挡住部分的距离,然后将期望的部分UI向上滑移(动画),这样,或许这就是那个你眼中“优雅的”解决方式。
PS: 根据生活经验,大厂APP早已抛弃这种在同一个界面同时输入手机号码跟验证码的方式,改为了输入手机号码发送验证码后跳转单独的验证码界面。现在立刻马上你或许可以跟产品battle, battle, 改变现有的设计方案~
登录按钮被遮挡影响体验.png
上代码:
var btnLocation: IntArray? = null
var scrollHeight = 0
lateinit var container: View
lateinit var btnLogin: View
fun softwareObserverAndTranslation() {
container.viewTreeObserver.addOnGlobalLayoutListener {
val r = Rect()
container.getWindowVisibleDisplayFrame(r)
if (btnLocation == null) {
btnLocation = IntArray(2)
btnLogin.getLocationOnScreen(btnLocation)
}
val cd = btnLocation!!
val screenHeight: Int = container.rootView.height
val softHeight = screenHeight - r.bottom
if (scrollHeight == 0 && softHeight > 120) {
scrollHeight = cd[1] + btnLogin.height - (screenHeight - softHeight)
scrollHeight += 5.dpToPx()
if (scrollHeight < 0) {
scrollHeight = 0
return@addOnGlobalLayoutListener
}
}
if (softHeight > 120) {
if (abs(container.translationY.toInt()) != scrollHeight) {
animationTranslationY(0, scrollHeight)
}
} else { //否则判断为输入法隐藏了
if (container.translationY < 10f) {
animationTranslationY(scrollHeight, 0)
}
}
}
}
private fun animationTranslationY(start: Int, end: Int) {
val animator = ValueAnimator.ofFloat(start.toFloat(), end.toFloat())
animator.duration = 250
animator.addUpdateListener { valueAnimator ->
container.translationY = -(valueAnimator.animatedValue as Float)
}
animator.start()
}