【发布时间】:2015-11-27 14:47:53
【问题描述】:
我有一个包含许多活动的应用程序,其布局适用于手机大小 (SFF) 和平板电脑大小 (LFF) 的设备。对于 LFF 设备,框架在方向更改(横向 纵向)时自动重新创建活动可以正常工作并且可以满足我的要求。在 SFF 设备上操作时,我可以使用 Activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) 将方向锁定为纵向。
在 SFF 设备上运行时,我想在设备物理旋转到横向时启动不同的活动。 (让我们暂且不讨论在轮换时启动不同的活动是否是一个好的设计原则。)
最初我使用OrientationEventListener 来监控旋转,但在“自然”方向为横向的 SFF 设备的情况下这会失败。 OrientationEventListener.onOrientationChanged() 将报告 0 度 (+/-45),WindowManager.getDefaultDisplay().getRotation() 将在横向时报告 Surface.ROTATION_0。我找不到一种方法来确定设备的“自然”方向以补偿报告的旋转值。有几个 SO 问题对此进行了讨论,但似乎都没有一个令人满意的答案。
另一种选择是在清单中使用android:configChanges="orientation|screenSize" 并捕捉onConfigurationChanged() 中的方向变化。这样做的问题是它破坏了 LFF 设备的默认行为,我希望保留这些行为。一个可怕的 hack 确实出现了:使用 LFF 和 SFF 版本复制清单中的每个活动,一个有一个没有android:configChanges 集,然后让活动在每次启动新活动时选择适当的版本。
我当前的解决方案既不使用android:configChanges,也不使用setRequestedOrientation() 和OrientationEventListener。相反,我有一个布尔资源is_landscape,在values-land 中定义,我在相关活动的onCreate() 中对此进行了测试。这样做的缺点是,在旋转到横向时:
- 即将启动横向活动的纯纵向活动,首先由框架重新创建,这相当昂贵并且可能会延迟横向活动的启动;和
- 仅纵向 Activity 将失去一些状态,否则框架通常会保留这些状态,并且在从横向 Activity 返回时可用。
谁能提出更好的解决方案,包括可能发现设备“自然”方向的方法?我需要这个才能恢复到 Android 4.0。
【问题讨论】: