You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android中SOFT_INPUT_ADJUST_RESIZE废弃后软输入模式切换方案

单Activity多Fragment架构软键盘新API迁移方案

核心疑问解答

  • 关于OnApplyWindowInsetsListener绑定位置:直接绑定在Activity的android.R.id.content根容器上即可,这是所有Fragment的承载容器,全局一次绑定就能覆盖所有页面场景,不需要每个Fragment单独设置监听。
  • 关于两种软键盘模式的运行时切换:不需要依赖废弃的SOFT_INPUT_ADJUST_RESIZE flag,自己维护一个全局模式标记位,在insets监听回调里根据当前模式决定是否将软键盘高度计入布局底部偏移即可,SOFT_INPUT_ADJUST_NOTHING的效果直接通过忽略软键盘inset值实现,完全不需要修改window的softInputMode属性。

具体实现步骤

1. Activity层基础配置

首先移除Manifest中Activity节点下的android:windowSoftInputMode="adjustResize"配置,在MainActivity中添加全局insets处理逻辑:

class MainActivity : AppCompatActivity() {
    // 当前软键盘适配模式,默认等效原adjustResize
    private var currentSoftInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // 关闭系统默认的窗口边距自适应,接管insets处理逻辑
        WindowCompat.setDecorFitsSystemWindows(window, false)
        val contentContainer = findViewById<FrameLayout>(android.R.id.content)

        // 给全局内容容器绑定insets监听
        ViewCompat.setOnApplyWindowInsetsListener(contentContainer) { _, insets ->
            val statusBarInsets = insets.getInsets(WindowInsetsCompat.Type.statusBars())
            val navBarInsets = insets.getInsets(WindowInsetsCompat.Type.navigationBars())
            val imeInsets = insets.getInsets(WindowInsetsCompat.Type.ime())

            // 计算底部边距:根据当前模式决定是否纳入软键盘高度
            val bottomPadding = if (currentSoftInputMode == WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE) {
                maxOf(navBarInsets.bottom, imeInsets.bottom)
            } else {
                // ADJUST_NOTHING模式下忽略软键盘高度,仅保留导航栏边距
                navBarInsets.bottom
            }
            // 给容器设置边距,避免内容顶到状态栏/导航栏/软键盘
            contentContainer.setPadding(0, statusBarInsets.top, 0, bottomPadding)
            insets
        }
    }

    // 暴露给Fragment调用的模式切换方法
    fun setSoftInputAdaptMode(mode: Int) {
        currentSoftInputMode = mode
        // 主动触发insets重算,保证切换立即生效
        ViewCompat.requestApplyInsets(findViewById(android.R.id.content))
    }
}

2. Fragment层调用逻辑

需要禁用resize适配的Fragment,直接在对应生命周期调用Activity暴露的切换方法即可,和你原有逻辑的调用时机完全一致:

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    // 进入页面时切换为不resize模式
    (requireActivity() as MainActivity).setSoftInputAdaptMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING)
    return inflater.inflate(R.layout.fragment_b, container, false)
}

override fun onDestroyView() {
    super.onDestroyView()
    // 页面销毁时切回默认resize模式
    (requireActivity() as MainActivity).setSoftInputAdaptMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)
}

适配注意事项

  • 上述实现的交互和原有逻辑完全一致:默认页面软键盘弹出时布局整体上移,指定页面软键盘弹出时直接覆盖在内容上层,不会触发布局重排。
  • 全局监听统一处理的方式比原有方案可控性更强,如果后续有沉浸式页面、特殊边距适配需求,只需要在对应Fragment中单独处理自身布局的insets即可,不会和全局逻辑冲突。
  • 不需要额外给window设置SOFT_INPUT_ADJUST_NOTHING flag,只要在insets回调中忽略软键盘高度,就能1:1还原原flag的效果,也不会触发任何废弃警告。

内容的提问来源于stack exchange,提问作者Marat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 13:45:33