我们为 Android Automotive OS (AAOS) 提供了汽车设置 (packages/apps/Car/Settings
)。汽车设置与手机设置 (packages/apps/Settings
) 不同。虽然汽车设置包含大家熟悉的一些手机设置,但提供的是车辆化的视觉界面,经过了防注意力分散优化,并且为原始设备制造商 (OEM) 提供很多自定义入口点。
除了下面介绍的汽车设置概览外,您还可以参考以下相关主题,详细了解汽车设置:
架构和准则
汽车设置中的大多数页面都是作为一系列扩展 SettingsFragment 的 fragment 实现的,每个 fragment 都在 CarSettingActivities 中定义自己的 activity。这些静态 activity 从 BaseCarSettingsActivity 进行扩展。此规则有一些例外情况,例如某些特殊 fragment 从 BaseFragment 而非 SettingsFragment
进行扩展,而一些 activity 位于 CarSettingActivities 之外,这些都应该视为例外情况(并非要遵循的模式)。
静态偏好设置
静态偏好设置在 XML 中使用 Preference 或 CarUiPreference 标记定义。SettingsFragment
实现使用 getPreferenceScreenResId()
方法定义哪个 XML 文件包含要显示的静态偏好设置列表。
动态偏好设置
动态偏好设置使用 PreferenceGroup 标记或 PreferenceGroup 的实现。
在汽车设置应用中,动态偏好设置表示一组常规偏好设置,可引导用户访问 CarSettings 中的其他页面,不过这些页面是通过偏好设置控制器添加的,而不是在 XML 中添加的。例如,“语言和输入偏好设置”下的“管理键盘偏好设置”基于系统是否允许使用这些输入法,将这些输入法动态添加到偏好设置页面。
操作栏
每个设置屏幕的顶部都有一个操作栏,其中可能包含“返回”导航、屏幕标题和辅助性操作微件(例如按钮和开关)。这些操作栏类似于 Android 提供的 ActionBar,但实际上属于自定义视图。在 Android 11 及更高版本中,此工具栏已纳入底盘基本布局中,该布局包含工具栏视图以及其余应用内容的帧布局。
辅助性操作微件是 MenuItem 类,应在相应 SettingsFragment
或 BaseFragment
的 onCreate
内创建。可见性、状态等属性应由 SettingsFragment
的业务逻辑中的 setter 进行控制。
// ExampleSettingsFragment.java public class ExampleSettingsFragment extends SettingsFragment { @Override protected List<MenuItem> getToolbarMenuItems() { return Collections.singletonList(mClearConfirmButton); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mButton = new MenuItem.Builder(getContext()) .setTitle(R.string.text) .setOnClickListener(mOnClickListener) .setUxRestrictions(CarUxRestrictions.UX_RESTRICTIONS_NO_SETUP) .build(); } private void updateState() { button.setVisible(false); } }
操作栏支持汽车设置中的防注意力分散优化。
创建时,在 MenuItem.Builder
中设置 UXRestrictions。
偏好设置控制器
每个设置页面都可以包含多个偏好设置。
有关这些组件之间的关系,请参阅下图:
图 1. CarSettings 组件
PreferenceController
是一个具有生命周期感知能力的组件,有助于封装与特定偏好设置相关的业务逻辑。PreferenceControllers
只能通过 XML 附加到相关偏好设置。
// example_settings_fragment.xml <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" xmlns:settings="http://schemas.android.com/apk/res-auto" android:title="@string/example_settings_title"> <Preference android:key="@string/pk_example_preference_key" android:title="@string/example_preference_title" settings:controller="com.android.car.settings.example.ExamplePreferenceController"/> </PreferenceScreen>
汽车设置明确禁止通过代码创建 PreferenceController
,以便您可以更轻松地修改设置层次结构,只需对 Java 代码做出极少的改动即可。
PreferenceController
可能需要一些动态数据才能正常运行。例如,用于关闭某个应用的通知的 PreferenceController
需要知道应该对哪个应用执行操作。由于 PreferenceControllers
始终在 XML 中定义,因此无法提供其他构造函数参数。这些附加值通过 PreferenceController
上的公共 setter 方法提供,并使用 SettingsFragment
中的 use(...)
方法进行设置。
// ExamplePreferenceController.java public class ExamplePreferenceContorller extends PreferenceController<Preference> { private ExampleArg mExampleArg; public ExamplePreferenceController(...) { ... } public void setExampleArg(ExampleArg exampleArg) { mExampleArg = exampleArg; } } // ExampleSettingsFragment.java public class ExampleSettingsFragment extends SettingsFragment { @Override @XmlRes protected int getPreferenceScreenResId() { Return R.xml.example_settings_fragment; } @Override public void onAttach(Context context) { ExampleArg arg = (ExampleArg) getArguments().getSerializeable(ARG_KEY); ExamplePreferenceController controller = use(ExamplePreferenceController.class, R.string.pk_example_preference_key); controller.setExampleArg(arg); } }
使用 use(...)
方法的频率越高,以极少改动 Java 代码的方式重新安排设置层次结构的初始目标就越难实现,因为需要将现有 fragment 代码的较大部分复制到新创建的 fragment 中。有一种方法可以最大限度降低这样做的难度,那就是:
- 尽量减少
use(...)
的使用。 - 尝试每次都在 Fragment 中的某个位置(例如,在
onAttach()
方法中)调用use(...)
。
intent 处理
应由汽车设置应用处理的所有 intent 均在清单文件中定义。通常,intent 的定义和处理方式与大多数标准 Android 应用相同,但所有 activity 和 intent 过滤器均在清单中定义。
更改根 fragment
如果需要,可使用 config_show_settings_root_exit_icon
显示或隐藏“退出”图标。
自定义主题
自定义其他属性和资源
汽车设置应用主要使用 CarSettingTheme
(Theme.CarUi
的扩展)。此主题用于对系统应用的外观和风格进行标准化,以确保整个系统的一致性。
自定义偏好设置
自定义偏好设置涵盖以下附加位置:
- 某些基本偏好设置类的布局在
car_preference
中定义,并针对汽车 build 进行叠加。此处可替换为基本偏好设置类的任何自定义布局。 - 汽车设置使用主要在
common
软件包中定义的自定义偏好设置。这些设置应在汽车设置模块中独立于基本偏好设置类进行叠加。