三星Galaxy S8全屏模式下FrameLayout随键盘上移技术问题咨询
问题根源分析
三星Galaxy S8的One UI在全屏模式下对adjustPan的处理逻辑和其他设备存在差异:当视图存在translation动画、焦点属性设置或层级叠加时,系统会优先选择移动带有焦点(focusable="true")的上层视图——也就是你这里的actHomeTopContainer,而忽略其他固定位置的视图(比如那个ImageView)。加上你之前执行了translationY动画,进一步干扰了系统的视图位置计算。
具体解决方案
1. 调整windowSoftInputMode与布局适配
尝试将android:windowSoftInputMode从adjustPan改为adjustResize,同时给底部容器添加fitsSystemWindows="true",让系统自动调整底部布局的大小而非移动整个视图:
<activity ... android:windowSoftInputMode="adjustResize">
修改布局中的actHomeBottomContainer:
<FrameLayout android:id="@+id/actHomeBottomContainer" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_alignParentBottom="true" android:background="@color/white" android:foregroundGravity="top" android:fitsSystemWindows="true" />
注意:如果你的应用是沉浸式全屏模式,需要确保
fitsSystemWindows属性正确传递到需要适配的视图上,否则adjustResize可能不生效。
2. 手动控制视图位置,抵消系统的自动上移
通过监听键盘的显示/隐藏事件,手动调整actHomeTopContainer的translationY值,抵消系统的移动:
// 在Activity中添加键盘监听 val rootView = window.decorView.rootView rootView.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener { override fun onGlobalLayout() { val r = Rect() rootView.getWindowVisibleDisplayFrame(r) val screenHeight = rootView.rootView.height val keyboardHeight = screenHeight - r.bottom // 键盘弹出时,保持顶部容器的动画位置;隐藏时重置 if (keyboardHeight > screenHeight * 0.15) { // 用阈值判定键盘是否弹出 actHomeTopContainer.translationY = -translateYSize } else { actHomeTopContainer.translationY = 0f } } })
3. 调整焦点属性,引导系统移动正确的视图
当前actHomeTopContainer设置了focusable="true"和focusableInTouchMode="true",这会让三星系统优先移动它。你可以把焦点转移到触发键盘的actHomeBottomContainer上:
<FrameLayout android:id="@+id/actHomeBottomContainer" ... android:focusable="true" android:focusableInTouchMode="true" />
同时在触发键盘的代码中,先让底部容器获取焦点:
actHomeBottomContainer.requestFocus() // 再执行弹出键盘的操作,比如调用EditText的requestFocus()
4. 针对三星One UI的特殊适配
如果是全屏手势或刘海屏导致的问题,可以在Activity的主题中添加以下配置:
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> ... <item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item> <item name="android:windowFullscreen">false</item> <!-- 若开启了全屏,尝试关闭 --> </style>
内容的提问来源于stack exchange,提问作者Nininea

