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

Jetpack Compose单Activity:不重启切换横竖屏的实现方法

解决方案:Jetpack Compose 单Activity横竖屏无重启切换实现

一、核心配置前提(必须修改Manifest)

要实现横竖屏切换不重启Activity,首先需要给目标Activity添加configChanges属性,覆盖系统默认的重启行为。同时保留初始的竖屏限制:

<activity
    android:name=".MainActivity"
    android:screenOrientation="portrait"
    android:configChanges="orientation|screenSize|smallestScreenSize"
    android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>
  • android:configChanges="orientation|screenSize|smallestScreenSize":告诉系统这三类配置变化由我们自己处理,不重启Activity
  • android:screenOrientation="portrait":保留初始竖屏锁定

二、完整Compose实现代码

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            val activity = LocalActivity.current
            // 可选:记录当前方向状态,用于UI逻辑控制(不需要可删除)
            val currentOrientation = remember { 
                mutableStateOf(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) 
            }

            // 监听系统配置变化,同步当前方向状态(可选)
            DisposableEffect(Unit) {
                val configListener = object : ComponentCallbacks {
                    override fun onConfigurationChanged(newConfig: Configuration) {
                        currentOrientation.value = if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
                            ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
                        } else {
                            ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
                        }
                    }

                    override fun onLowMemory() {}
                }
                activity.registerComponentCallbacks(configListener)
                onDispose {
                    activity.unregisterComponentCallbacks(configListener)
                }
            }

            // 横屏状态下拦截返回键,切回竖屏
            BackHandler(currentOrientation.value == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
                activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
            }

            MyAppTheme {
                Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
                    Column(
                        modifier = Modifier
                            .fillMaxSize()
                            .padding(innerPadding)
                            .padding(16.dp),
                        verticalArrangement = Arrangement.Center,
                        horizontalAlignment = Alignment.CenterHorizontally
                    ) {
                        Button(
                            onClick = {
                                // 切换至横屏
                                activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
                            },
                            enabled = currentOrientation.value != ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
                        ) {
                            Text("切换到横屏")
                        }

                        // 可选:显示当前方向状态
                        Text(
                            text = if (currentOrientation.value == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) "当前横屏" else "当前竖屏",
                            modifier = Modifier.padding(top = 16.dp)
                        )
                    }
                }
            }
        }
    }

    // 可选:全局配置变化回调(非Compose场景使用)
    override fun onConfigurationChanged(newConfig: Configuration) {
        super.onConfigurationChanged(newConfig)
        // 可处理非Compose的UI调整逻辑
    }
}

三、关键细节说明

  1. 避免Activity重启:Manifest的configChanges配置是核心,缺少则系统会强制重启Activity
  2. 安全获取Activity实例:使用LocalActivity.current替代context as Activity,避免类型转换风险
  3. 返回键拦截逻辑:BackHandler仅在横屏状态下生效,按下返回键直接切回竖屏,且消费返回事件,不会触发默认返回行为
  4. 方向切换的正确性:切回竖屏时使用SCREEN_ORIENTATION_PORTRAIT而非UNSPECIFIED,确保严格回到初始竖屏状态,避免系统自动选择方向
  5. 无重组保证:方向切换操作直接调用Activity的API,不会触发Compose重组;若需UI响应方向变化,可通过DisposableEffect监听配置变化,仅在必要时更新状态

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 04:20:09