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":告诉系统这三类配置变化由我们自己处理,不重启Activityandroid: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调整逻辑 } }
三、关键细节说明
- 避免Activity重启:Manifest的
configChanges配置是核心,缺少则系统会强制重启Activity - 安全获取Activity实例:使用
LocalActivity.current替代context as Activity,避免类型转换风险 - 返回键拦截逻辑:
BackHandler仅在横屏状态下生效,按下返回键直接切回竖屏,且消费返回事件,不会触发默认返回行为 - 方向切换的正确性:切回竖屏时使用
SCREEN_ORIENTATION_PORTRAIT而非UNSPECIFIED,确保严格回到初始竖屏状态,避免系统自动选择方向 - 无重组保证:方向切换操作直接调用Activity的API,不会触发Compose重组;若需UI响应方向变化,可通过
DisposableEffect监听配置变化,仅在必要时更新状态
内容的提问来源于stack exchange,提问作者Anees Ahmad
相关产品推荐
相关产品推荐

