在 Android 8.0 中,用户可以使用快速设置磁贴或显示设置在自动旋转和纵向旋转模式之间切换。在 Android 9 中,我们更新了纵向旋转模式,通过固定当前屏幕旋转来消除意外旋转,即使设备位置发生变化也是如此。用户可以在需要时通过按导航栏中的新按钮来手动触发旋转。我们将纵向模式重命名为旋转锁定,并在自动旋转关闭时激活。自动旋转模式没有变化。
当设备处于旋转锁定模式时,用户可以将屏幕锁定到顶部可见 Activity 支持的任何旋转(考虑到当前系统限制)。如果顶部 Activity 可以在自动旋转模式下以多次旋转方式呈现,则相同的选项应该在旋转锁定模式下可用,但基于 Activity 的screenOrientation
设置有一些例外。
旋转锁定模式的工作原理是在设备旋转发生变化时在导航栏中显示一个按钮。为了实现这一点,即使自动旋转关闭,设备的方向传感器也必须保持活动状态。点击此按钮可有效设置用户轮换首选项 ( Settings.System.USER_ROTATION
)。 WindowManager 使用此首选项以及有关顶级 Activity 和系统状态的其他详细信息来更改系统的旋转。在移动到另一个 Activity 时决定以何种旋转方式呈现系统时,WindowManager 继续使用用户旋转首选项。
![此 gif 显示手机处于横向方向,屏幕处于纵向方向。出现一个图标询问用户是否要将屏幕方向更改为横向。](https://source.android.google.cn/static/docs/core/display/images/rotate-btn-quickstep.gif?authuser=6&hl=sr)
在活动之间移动时,应保持用户轮换偏好。然而,由于大多数手机用户只想在短时间内处于横向状态,因此我们添加了自然方向偏差。每当系统旋转更改为设备的自然方向时,用户旋转首选项就会重置为设备的自然方向。对于大多数手机,设备的自然方向是纵向 (0°)。当使用仅限纵向的应用程序、锁定手机或返回启动器工作区时,经常会发生重置用户旋转首选项的情况。
在过去十年中,用户的旋转交互没有太大变化。鉴于用户之前在导航栏中进行旋转和按钮定位的历史记录,用户可能会发现很难发现此功能。因此,我们为旋转按钮添加了介绍模式,当它出现时会突出显示它。介绍模式行为仅发生在前几个按钮交互中,之后介绍模式被禁用。
来源
Android 9 中添加了对旋转建议的支持。大多数更改包含在以下文件中。
-
services/.../server/policy/PhoneWindowManager.java
:- 消耗
WindowOrientationListener
输出的钩子(MyOrientationListener
,负责监视传感器以确定设备是否已旋转) - 即使自动旋转被禁用,也使
WindowOrientationListener
保持活动状态(请参阅needSensorRunningLp()
) - 计算给定用户旋转首选项、顶部 Activity
screenOrientation
设置和系统状态的系统旋转(请参阅rotationForOrientationLw()
) - 确定顶部 Activity 是否可以旋转到给定的旋转(请参阅
isRotationChoicePossible()
)
- 消耗
-
SystemUI/.../statusbar/phone/NavigationBarFragment
:- 确定导航栏按钮是否应显示在来自
PhoneWindowManager
的旋转建议回调中(请参阅onRotationProposal()
) - 处理何时隐藏旋转导航栏按钮(请参阅对
setRotateSuggestionButtonState(false)
的调用) - 处理按钮超时,包括导航栏隐藏时的特殊情况(通常是全屏)
- 返回设备自然方向时重置用户首选项 (
mRotationWatcher
) - 为导航栏按钮动画选择适当的样式,应用于
NavigationBarView
(请参阅onRotationProposal()
) - 添加介绍模式逻辑,包括专门的动画(请参阅对
Settings.Secure.NUM_ROTATION_SUGGESTIONS_ACCEPTED
的引用) - 实现disable2旋转标志(参见
disable()
)
- 确定导航栏按钮是否应显示在来自
-
SystemUI/.../statusbar/phone/NavigationBarView.java
:- 设置按钮图标动画的样式以匹配挂起的旋转(请参阅
updateRotateSuggestionButtonStyle()
) - 处理按钮可见性更改(请参阅
setRotateButtonVisibility()
),包括在某些辅助功能服务处于活动状态时隐藏旋转按钮的逻辑(考虑最右侧的导航栏按钮堆栈排名)
- 设置按钮图标动画的样式以匹配挂起的旋转(请参阅
-
SystemUI/res/layout/menu_ime.xml
:- 包括用于旋转按钮的新
KeyButtonView
,堆叠在菜单和 IME/键盘选择器上方,但在辅助功能按钮下方
- 包括用于旋转按钮的新
SystemUI/res/drawable/ic_sysbar_rotate_button.xml
:- 复杂的
AnimatedVectorDrawable
用于为旋转导航栏按钮设置动画 - 样式(在
SystemUI/res/values/styles.xml
中)用于设置旋转的开始和结束角度,因此可以使用相同的可绘制动画来设置各种开始和结束旋转的动画 - 图标着色通过
TintedKeyButtonDrawable
设置
- 复杂的
执行
Android 9 包含所有必要的更改,以使旋转建议适用于使用软件导航键(后退、主页等)的设备。
创建带有硬件导航键的设备并希望实现此功能的设备制造商将需要设计和实现自己的系统 UI 功能或禁用该功能。建议当设备与当前系统旋转成 90° 或 180° 时,任何引入的表面都易于使用,并且可以快速访问。由于这些原因,不建议使用通知(如对 IME/键盘选择器所做的那样)。
使用此功能的硬件要求与使用自动旋转的要求相同。
为了实现一致性,当系统在自动旋转关闭时出于任何原因更改为设备的自然旋转时,用户旋转首选项 ( Settings.System.USER_ROTATION
) 必须重置为设备的自然旋转。提供的实现可以执行此操作(请参阅NavigationBarFragment.mRotationWatcher
)。
StatusBarManager.disable2
中有一个新标志可以暂时阻止出现旋转建议。请参阅StatusBarManager.DISABLE2_ROTATE_SUGGESTIONS
。在所有实现中都必须遵守此标志,因为它由关键系统应用程序(包括设置向导)使用。提供的实现支持这一点(请参阅NavigationBarFragment.disable()
)。
如果可能的话,我们强烈建议启用该功能并遵循 AOSP 实施。我们的目标是保持设备之间的旋转体验相似,反映当今大多数手机上自动旋转和纵向锁定之间体验的一致性。
定制化
由于旋转建议仅在旋转锁定模式(自动旋转关闭)下出现,因此可以通过选择默认情况下自动旋转关闭来选择该功能是否对于新安装默认打开。请参阅SettingsProvider/res/values/defaults.xml
中的def_accelerometer_rotation
以进行默认更改。
用户可以通过快速设置或显示设置中的旋转图块轻松更改自动旋转是否处于活动状态(无论默认值如何)。
验证
为了进行测试,可以通过更改门控Settings.Secure
值来关闭和打开该功能。通过从特权 adb 实例运行以下命令,可以最轻松地完成此操作:
adb shell settings put secure show_rotation_suggestions <x>
将 x 设置为0
表示关闭,设置为1
表示打开。
为了进行测试,可以通过更改关联的Settings.Secure
值来重置介绍模式。通过从特权 adb 实例运行以下命令,可以最轻松地完成此操作:
adb shell settings put secure num_rotation_suggestions_accepted 0