27、车载系统服务:SystemUI定制、StatusBar与NavigationBar、系统对话框、系统级通知
各位同学,今天我们来聊聊车载系统里最“露脸”的部分——SystemUI。说白了,就是用户每天开车时眼睛盯着的那块屏幕上的所有东西:顶部的状态栏、底部的导航栏、弹出来的对话框、还有那些飘出来的通知。这部分做得好不好,直接决定了用户觉得你这车机“专不专业”。
我个人习惯把SystemUI比作车机的“脸面”。你想想看,底层服务再牛,如果UI卡顿、布局混乱,用户第一印象就差了。我在项目里见过太多“功能强大但界面粗糙”的车机,最后都被用户吐槽。所以,这块值得我们花功夫。
27.1 SystemUI 整体架构
SystemUI在Android Automotive OS里是一个独立的APK,它不像手机版那样跟系统紧密耦合。车载版SystemUI需要更灵活,因为不同车型的屏幕尺寸、形状、分辨率差异太大了。
它的核心模块包括:
- StatusBar:显示时间、信号、电量、蓝牙等状态图标。
- NavigationBar:提供返回、主页、最近任务(以及空调、座椅等快捷控制)。
- 系统对话框:比如音量调节、驾驶模式切换、警告弹窗。
- 系统级通知:来自地图、音乐、电话等应用的通知。
嗯,这里要注意,车载SystemUI的定制通常不是改改图标颜色那么简单。很多车厂会要求完全重写布局,甚至把StatusBar和NavigationBar合并成一条“任务栏”。
核心原则:车载SystemUI必须保证驾驶安全。任何交互都不能让驾驶员分心超过2秒。所以,我们定制时,信息要精简,操作要直观。
27.2 StatusBar 定制实战
StatusBar在车载上通常比手机更简洁。手机上有电池百分比、双卡信号、通知图标一大堆,车上不需要这些。我建议只保留:时间、蓝牙连接状态、网络信号、以及一个“驾驶模式”指示器。
定制StatusBar,最直接的方式是修改SystemUI的布局文件。比如,在status_bar.xml里,你可以调整图标顺序、添加自定义View。
<!-- 车载StatusBar示例 -->
<com.android.systemui.statusbar.AlphaOptimizedFrameLayout
android:layout_width="match_parent"
android:layout_height="48dp"
android:background="@color/car_status_bar_bg">
<!-- 左侧:时间 -->
<TextView
android:id="@+id/clock"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:textSize="16sp"
android:textColor="@android:color/white"
android:paddingStart="16dp"/>
<!-- 右侧:状态图标区 -->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="end"
android:orientation="horizontal"
android:paddingEnd="16dp">
<!-- 蓝牙、信号、电量等图标 -->
</LinearLayout>
</com.android.systemui.statusbar.AlphaOptimizedFrameLayout>
我在项目中遇到过一个问题:某款车型的屏幕是圆形的,标准的StatusBar放上去很难看。后来我们干脆把StatusBar做成了半圆弧形,沿着屏幕边缘走。这需要重写onLayout方法,但效果确实好。
小技巧:车载StatusBar的高度建议不低于48dp,但也不超过64dp。太矮了手指不好点,太高了占内容区域。我一般用56dp,视觉上比较平衡。
27.3 NavigationBar 定制要点
NavigationBar在车上承担了更多职责。除了传统的三键(返回、主页、最近任务),很多车厂会把空调控制、座椅加热、音量旋钮也集成进来。这就不是简单的“隐藏或显示”了,而是需要动态添加按钮。
我建议的做法是:在NavigationBar里预留一个FlexboxLayout,然后通过配置动态加载按钮。这样不同车型只需要改配置文件,不用改代码。
// 动态添加快捷按钮示例
FlexboxLayout navContainer = findViewById(R.id.nav_buttons);
List<NavButton> buttons = getConfigButtons(); // 从配置文件读取
for (NavButton btn : buttons) {
View buttonView = LayoutInflater.from(this)
.inflate(R.layout.nav_button_item, navContainer, false);
// 设置图标、点击事件
navContainer.addView(buttonView);
}
嗯,这里有个坑。我曾经在某个项目里,把空调控制直接塞进NavigationBar,结果发现空调状态变化时,NavigationBar需要频繁刷新,导致导航动画掉帧。后来我们把空调状态抽成一个独立的LiveData,只在状态变化时更新对应的图标,问题就解决了。
注意:不要在NavigationBar里放太多按钮。根据NHTSA(美国国家公路交通安全管理局)的建议,驾驶中可交互的元素不超过7个。我一般控制在5个以内,包括系统三键。
27.4 系统对话框定制
车载系统对话框跟手机有很大不同。手机上的对话框可以很花哨,但车上必须简洁、大字体、高对比度。而且,很多对话框需要支持“驾驶模式”下的特殊交互——比如语音控制。
举个例子,音量调节对话框。手机上是竖条滑块,车上我建议做成横向的,而且显示当前音量等级(1-10)。这样驾驶员扫一眼就知道音量大小,不用仔细看。
<!-- 车载音量对话框布局 -->
<LinearLayout
android:layout_width="300dp"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical"
android:padding="16dp"
android:background="@drawable/car_dialog_bg">
<ImageView android:src="@drawable/ic_volume" />
<SeekBar
android:id="@+id/volume_slider"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:max="10"
android:progress="5"/>
<TextView
android:id="@+id/volume_level"
android:text="5"
android:textSize="18sp"
android:textColor="@android:color/white"
android:paddingStart="8dp"/>
</LinearLayout>
我习惯在对话框出现时,同时触发一个短暂的震动反馈(Haptic Feedback)。这样驾驶员即使不看屏幕,也知道有对话框弹出来了。但注意,震动不能太长,200毫秒以内就够了。
27.5 系统级通知定制
车载通知跟手机通知最大的区别是:不能打扰驾驶。手机可以响铃+震动+弹窗,车上只能“轻提醒”。我建议的做法是:通知只出现在StatusBar的左侧,以图标形式显示,点击后才展开详情。
另外,通知的优先级在车上需要重新定义。比如,导航提示的优先级应该高于音乐播放通知。我们可以通过修改NotificationChannel的importance来实现。
// 创建车载通知渠道示例
NotificationChannel carChannel = new NotificationChannel(
"car_navigation",
"导航提示",
NotificationManager.IMPORTANCE_HIGH // 高优先级,但不会弹出全屏
);
carChannel.setDescription("导航相关的转弯、测速提醒");
carChannel.setShowBadge(false); // 不显示角标
notificationManager.createNotificationChannel(carChannel);
我曾经踩过一个坑:某款车机在收到多条通知后,StatusBar的通知图标重叠在一起,看不清。后来我们限制了StatusBar上最多显示3个通知图标,多余的通知折叠成一个“更多”图标。用户点击后展开列表。这个方案后来成了我们团队的标配。
避坑指南:车载通知的点击事件一定要慎重。不要在通知上放“确认”或“取消”按钮,因为驾驶员可能误触。我建议只放一个“查看详情”的intent,点击后打开对应的应用页面。
27.6 总结与个人经验
SystemUI定制,说白了就是在“安全”和“功能”之间找平衡。我做了这么多项目,最大的体会是:少即是多。用户开车时不需要花哨的动画,不需要复杂的设置。他们需要的是:一眼看清时间、信号、导航提示,随手能调音量、切歌、开空调。
如果你刚开始接触车载SystemUI,我建议你先从StatusBar和NavigationBar的布局改起。把默认的图标换成符合车机风格的,把间距调大,把字体加粗。这些改动虽然简单,但用户感知最明显。
最后,记住一点:车载系统不是手机的移植版。它是为驾驶场景量身定做的。你做的每一个UI决策,都要问自己一句:“这个功能在时速120公里时,驾驶员能安全操作吗?”