在不重新启动当前 activity 的情况下在方向更改时调用 activity
Invoke activity on orientation change without restarting current activity
我有一个包含许多活动的应用程序,它的布局适合 phone 大小的 (SFF) 和平板电脑大小的 (LFF) 设备。对于 LFF 设备,框架在方向更改(横向 <-> 纵向)时自动重新创建活动,效果很好,可以满足我的要求。在 SFF 设备上操作时,我可以使用 Activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
.
将方向锁定为纵向
当 运行 在 SFF 设备上时,我想在设备物理旋转到横向时启动不同的 activity。 (让我们暂且不讨论在旋转时启动不同的 activity 是否是一个好的设计原则。)
最初我在横向时使用 OrientationEventListener
to monitor the rotation but this fails in the case of an SFF device whose "natural" orientation is landscape. OrientationEventListener.onOrientationChanged()
will report 0 degrees (+/-45) and WindowManager.getDefaultDisplay().getRotation()
will report Surface.ROTATION_0
。我无法找到一种方法来确定设备的 "natural" 方向以补偿报告的旋转值。有几个 SO 问题讨论了这个问题,但 none 似乎有一个令人满意的答案。
另一种选择是使用 android:configChanges="orientation|screenSize"
in the manifest and catch the orientation change in onConfigurationChanged()
。这样做的问题是它破坏了 LFF 设备的默认行为,而我希望保留这种行为。一个可怕的 hack 确实出现了:用 LFF 和 SFF 版本复制清单中的每个 activity,一个有 android:configChanges
集,一个没有 android:configChanges
集,然后让 activity 每个选择合适的版本是时候启动新的 activity.
我当前的解决方案既不使用 android:configChanges
也不使用 setRequestedOrientation()
和 OrientationEventListener
。相反,我有一个布尔资源 is_landscape
,定义在 values-land
中,我在相关活动的 onCreate()
中对此进行了测试。这有缺点,在旋转到景观时:
- 即将启动横向 activity 的仅纵向 activity,首先由框架重新创建,这相当昂贵并且可以延迟横向的启动 activity;和
- 仅纵向 activity 将丢失一些状态,否则这些状态通常会被框架保留,并且在 return 时可以从横向 activity.
谁能提出更好的解决方案,包括可能发现设备 "natural" 方向的方法?我需要这个才能回到 Android 4.0.
您必须使用 getRotation
和 getResources().getConfiguration()
的组合来检查自然方向。
public int getDefaultOrientation() {
WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
Configuration config = getResources().getConfiguration();
int rotation = windowManager.getDefaultDisplay().getRotation();
if ( ((rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) &&
config.orientation == Configuration.ORIENTATION_LANDSCAPE)
|| ((rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) &&
config.orientation == Configuration.ORIENTATION_PORTRAIT)) {
return Configuration.ORIENTATION_LANDSCAPE;
} else {
return Configuration.ORIENTATION_PORTRAIT;
}
}
我有一个包含许多活动的应用程序,它的布局适合 phone 大小的 (SFF) 和平板电脑大小的 (LFF) 设备。对于 LFF 设备,框架在方向更改(横向 <-> 纵向)时自动重新创建活动,效果很好,可以满足我的要求。在 SFF 设备上操作时,我可以使用 Activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
.
当 运行 在 SFF 设备上时,我想在设备物理旋转到横向时启动不同的 activity。 (让我们暂且不讨论在旋转时启动不同的 activity 是否是一个好的设计原则。)
最初我在横向时使用 OrientationEventListener
to monitor the rotation but this fails in the case of an SFF device whose "natural" orientation is landscape. OrientationEventListener.onOrientationChanged()
will report 0 degrees (+/-45) and WindowManager.getDefaultDisplay().getRotation()
will report Surface.ROTATION_0
。我无法找到一种方法来确定设备的 "natural" 方向以补偿报告的旋转值。有几个 SO 问题讨论了这个问题,但 none 似乎有一个令人满意的答案。
另一种选择是使用 android:configChanges="orientation|screenSize"
in the manifest and catch the orientation change in onConfigurationChanged()
。这样做的问题是它破坏了 LFF 设备的默认行为,而我希望保留这种行为。一个可怕的 hack 确实出现了:用 LFF 和 SFF 版本复制清单中的每个 activity,一个有 android:configChanges
集,一个没有 android:configChanges
集,然后让 activity 每个选择合适的版本是时候启动新的 activity.
我当前的解决方案既不使用 android:configChanges
也不使用 setRequestedOrientation()
和 OrientationEventListener
。相反,我有一个布尔资源 is_landscape
,定义在 values-land
中,我在相关活动的 onCreate()
中对此进行了测试。这有缺点,在旋转到景观时:
- 即将启动横向 activity 的仅纵向 activity,首先由框架重新创建,这相当昂贵并且可以延迟横向的启动 activity;和
- 仅纵向 activity 将丢失一些状态,否则这些状态通常会被框架保留,并且在 return 时可以从横向 activity.
谁能提出更好的解决方案,包括可能发现设备 "natural" 方向的方法?我需要这个才能回到 Android 4.0.
您必须使用 getRotation
和 getResources().getConfiguration()
的组合来检查自然方向。
public int getDefaultOrientation() {
WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
Configuration config = getResources().getConfiguration();
int rotation = windowManager.getDefaultDisplay().getRotation();
if ( ((rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) &&
config.orientation == Configuration.ORIENTATION_LANDSCAPE)
|| ((rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) &&
config.orientation == Configuration.ORIENTATION_PORTRAIT)) {
return Configuration.ORIENTATION_LANDSCAPE;
} else {
return Configuration.ORIENTATION_PORTRAIT;
}
}