Android分屏模式下如何通过代码程序化切换视图
Android分屏模式下的程序化视图切换实现
核心适配前提
- 需在
AndroidManifest.xml的目标Activity标签下配置android:resizeableActivity="true",否则分屏模式下系统会直接销毁重建Activity,导致切换操作丢失 - 若应用固定了屏幕方向(配置了
android:screenOrientation),分屏模式会被系统禁用,需移除相关配置或动态适配方向 - 分屏模式触发的尺寸变更会引发生命周期回调,切换操作需避免在状态未初始化完成时执行,防止视图引用丢失
- 分屏模式下的Fragment切换必须使用
commitAllowingStateLoss()替代普通commit(),否则会因Activity状态保存抛出异常
场景1:单Activity多Fragment架构切换(主流实现)
该场景下直接复用Fragment切换逻辑,仅需增加分屏状态的任务暂存机制,代码示例:
class MainActivity : AppCompatActivity() { // 暂存分屏重建期间待执行的切换任务 private var pendingTargetFragment: Class<out Fragment>? = null // 标记视图是否完成初始化 private var isViewReady = false override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) isViewReady = true } override fun onDestroy() { super.onDestroy() isViewReady = false } // 分屏状态变更回调,处理重建后的待执行任务 override fun onMultiWindowModeChanged(isInMultiWindowMode: Boolean, newConfig: Configuration?) { super.onMultiWindowModeChanged(isInMultiWindowMode, newConfig) pendingTargetFragment?.let { switchToFragment(it) pendingTargetFragment = null } } /** * 程序化切换Fragment的核心方法 * @param targetFragmentCls 目标Fragment的类对象 */ fun switchToFragment(targetFragmentCls: Class<out Fragment>) { // 视图未初始化完成时暂存任务,避免空指针 if (!isViewReady) { pendingTargetFragment = targetFragmentCls return } // 复用已有Fragment实例,避免重复创建 val targetFragment = supportFragmentManager .findFragmentByTag(targetFragmentCls.simpleName) ?: targetFragmentCls.newInstance() supportFragmentManager.beginTransaction() .replace(R.id.fragment_container, targetFragment, targetFragmentCls.simpleName) .addToBackStack(null) // 分屏场景专用提交方法,避免状态保存异常 .commitAllowingStateLoss() } }
Java实现逻辑与上述Kotlin代码完全一致,仅需替换对应语法即可,Fragment提交同样使用commitAllowingStateLoss()方法。
场景2:纯View层级切换(无Fragment架构)
对于直接操作View层级的场景,仅需在分屏重建后重新校验View引用有效性即可,代码示例:
/** * 程序化切换容器内的View * @param targetView 要显示的目标View * @param container 承载视图的父容器 */ fun switchViewInContainer(targetView: View, container: ViewGroup) { // 隐藏容器内所有现有View for (childIndex in 0 until container.childCount) { container.getChildAt(childIndex).visibility = View.GONE } // 目标View未添加到容器时先完成添加 if (targetView.parent == null) { container.addView(targetView) } targetView.visibility = View.VISIBLE } // 分屏状态变更时的适配处理 override fun onMultiWindowModeChanged(isInMultiWindowMode: Boolean, newConfig: Configuration?) { super.onMultiWindowModeChanged(isInMultiWindowMode, newConfig) // 分屏重建后重新获取当前显示View的引用,避免空指针 currentVisibleView = container.findViewById(currentVisibleView.id) }
内容的提问来源于stack exchange,提问作者Bluesea
相关产品推荐
相关产品推荐

