车载设置(packages/apps/Car/Settings
)是专门为 Android Automotive OS (AAOS) 提供的。车载设置与手机设置(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 应用中,动态偏好设置代表一组正常的偏好设置,这些偏好设置将用户定向到 CarSettings 内的其他页面,但这些偏好设置是通过 偏好设置控制器 而不是在 XML 中添加的。一个示例是“语言和输入”偏好设置下的“管理键盘”偏好设置,它会根据是否允许这些输入法,动态地将输入法添加到偏好设置页面。
操作栏
每个设置屏幕的顶部都有一个操作栏,其中可以包含“返回”导航、屏幕标题和补充操作微件(例如,按钮和开关)。这些操作栏类似于 Android 提供的 ActionBar,但实际上是自定义视图。在 Android 11 及更高版本中,此工具栏包含在底盘基本布局中,其中包含工具栏的视图和一个用于应用其余内容的 FrameLayout。
补充操作微件是 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
是一个生命周期感知型组件,有助于封装与特定偏好设置相关的业务逻辑。PreferenceController
只能通过 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
需要知道要对哪个应用执行操作。由于 PreferenceController
始终在 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(...)
的使用。 - 尝试将对
use(...)
的每次调用都放在 Fragment 中的一个位置(例如,在onAttach()
方法中)。
Intent 处理
Car Settings 应用应处理的所有 Intent 都在 清单文件中定义。Intent 通常像大多数标准 Android 应用一样定义和处理,所有 Activity 和 Intent 过滤器都在清单中定义。
更改根 Fragment
如果需要,可以使用 config_show_settings_root_exit_icon
显示或隐藏“退出”图标。
自定义主题
自定义其他属性和资源
Car Settings 应用主要使用 CarSettingTheme
,它是 Theme.CarUi
的扩展。此主题用于标准化系统应用的外观,以确保系统中的一致性。
自定义偏好设置
自定义偏好设置跨越以下其他位置
- 某些基本偏好设置类的布局在
car_preference
和 叠加中为车载版本定义。基本偏好设置类的任何自定义布局都可以在此处替换。 - Car Settings 使用主要在
common
软件包中定义的一些自定义偏好设置。这些应在 Car Settings 模块中与基本偏好设置类分开叠加。