CoordinatorLayout滚动异常:软键盘弹出时AppBarLayout消失求助
解决CoordinatorLayout软键盘弹出时AppBarLayout消失的问题
这个问题我之前也碰到过,确实挺头疼的——明明滚动折叠AppBar到Toolbar的功能正常,一弹软键盘AppBar就直接滑出屏幕不见了。不过别担心,咱们可以通过监听软键盘的显示/隐藏状态,配合控制AppBarLayout的折叠行为来解决,既能保留原来的滚动折叠功能,又能让软键盘弹出时AppBar乖乖缩成Toolbar停在顶部。
核心思路
当软键盘弹出时,主动将AppBarLayout折叠到Toolbar的高度,并临时锁定它的拖动行为;当软键盘隐藏时,恢复AppBar的正常滚动折叠功能。我们可以通过监听根布局(CoordinatorLayout)的尺寸变化来判断软键盘的状态,因为adjustResize模式下,软键盘弹出会挤压布局高度。
具体实现步骤
1. 准备布局引用
先在Activity里获取到关键布局的实例:
val coordinatorLayout = findViewById<CoordinatorLayout>(R.id.coordinator_layout) val appBarLayout = findViewById<AppBarLayout>(R.id.app_bar_layout) val toolbar = findViewById<Toolbar>(R.id.toolbar)
2. 获取Toolbar的高度
我们需要知道折叠后AppBar应该停留的高度,也就是Toolbar的实际高度:
var toolbarHeight = 0 // 等待Toolbar布局完成后获取高度 toolbar.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener { override fun onGlobalLayout() { toolbarHeight = toolbar.height // 获取到高度后移除监听,避免重复触发 toolbar.viewTreeObserver.removeOnGlobalLayoutListener(this) } })
3. 监听布局变化判断软键盘状态
给CoordinatorLayout添加全局布局监听,通过布局高度的变化判断软键盘是否弹出:
coordinatorLayout.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener { private var previousLayoutHeight = 0 override fun onGlobalLayout() { val currentLayoutHeight = coordinatorLayout.height // 初始化记录初始高度 if (previousLayoutHeight == 0) { previousLayoutHeight = currentLayoutHeight return } // 用高度差判断软键盘状态(阈值200可根据设备调整,也可以用屏幕比例) val isKeyboardVisible = currentLayoutHeight < previousLayoutHeight - 200 if (isKeyboardVisible) { // 软键盘弹出:折叠AppBar到Toolbar高度,带动画 appBarLayout.setExpanded(false, true) // 临时锁定AppBar,避免用户拖动它 val appBarParams = appBarLayout.layoutParams as CoordinatorLayout.LayoutParams val appBarBehavior = appBarParams.behavior as? AppBarLayout.Behavior appBarBehavior?.setDragCallback(object : AppBarLayout.Behavior.DragCallback() { override fun canDrag(appBarLayout: AppBarLayout): Boolean { return false // 禁止拖动AppBar } }) } else { // 软键盘隐藏:恢复AppBar的展开状态和拖动功能 appBarLayout.setExpanded(true, true) val appBarParams = appBarLayout.layoutParams as CoordinatorLayout.LayoutParams val appBarBehavior = appBarParams.behavior as? AppBarLayout.Behavior appBarBehavior?.setDragCallback(null) // 恢复默认拖动行为 } // 更新记录的布局高度 previousLayoutHeight = currentLayoutHeight } })
4. 确认Activity的软键盘模式
确保你的Activity在AndroidManifest.xml中已经设置了adjustResize,这是监听布局变化的前提:
<activity android:name=".YourTargetActivity" android:windowSoftInputMode="adjustResize"> </activity>
额外优化建议
- 阈值调整:如果200的高度差在某些设备上判断不准确,可以换成基于屏幕高度的比例,比如
previousLayoutHeight * 0.1(屏幕高度的10%)作为阈值。 - 焦点联动:可以配合EditText的焦点监听,在EditText获取焦点时就触发折叠,失去焦点时恢复,和布局监听形成双重保障。
这样处理后,滚动折叠的功能完全保留,软键盘弹出时AppBar会自动缩成Toolbar停在顶部,不会再滑出屏幕啦~
内容的提问来源于stack exchange,提问作者AouledIssa
相关产品推荐
相关产品推荐

