Android SystemUI——CarSystemBar添加到窗口(十)
上一篇文章我们看到了车载状态栏 CarSystemBar 视图的创建流程,这里我们继续分析将车载状态栏添加到 Windows 窗口中。
一、添加状态栏到窗口
前面我们已经分析了构建视图对象容器和构建视图对象内容,接下来我们继续分析 attachNavBarWindows() 方法将视图对象添加到 Window 中。
1、CarSystemBar
源码位置:/packages/apps/Car/SystemUI/src/com/android/systemui/car/systembar/CarSystemBar.java
attachNavBarWindows
private final SystemBarConfigs mSystemBarConfigs;
private void attachNavBarWindows() {
mSystemBarConfigs.getSystemBarSidesByZOrder().forEach(this::attachNavBarBySide);
}
attachNavBarWindows() 会调用 SystemBarConfigs 的 getSystemBarSidesByZOrder() 方法获取到当前存在的所有 SystemBar 所对应的 Side。
2、SystemBarConfigs
源码位置:/packages/apps/Car/SystemUI/src/com/android/systemui/car/systembar/SystemBarConfigs.java
private final List<@SystemBarSide Integer> mSystemBarSidesByZOrder = new ArrayList<>();
protected List<Integer> getSystemBarSidesByZOrder() {
return mSystemBarSidesByZOrder;
}
可以看到这里返回一个 List<@SystemBarSide Integer> 类型的数组,下面看一下 mSystemBarSidesByZOrder 数据的赋值。
sortSystemBarSidesByZOrder
private final Map<@SystemBarSide Integer, SystemBarConfig> mSystemBarConfigMap = new ArrayMap<>();
private void sortSystemBarSidesByZOrder() {
// 获取SystemBarConfig列表
List<SystemBarConfig> systemBarsByZOrder = new ArrayList<>(mSystemBarConfigMap.values());
systemBarsByZOrder.sort(new Comparator<SystemBarConfig>() {
@Override
public int compare(SystemBarConfig o1, SystemBarConfig o2) {
// 进行大小比较
return o1.getZOrder() - o2.getZOrder();
}
});
// 存储排序后SystemBar的Side数值。
systemBarsByZOrder.forEach(systemBarConfig -> {
mSystemBarSidesByZOrder.add(systemBarConfig.getSide());
});
}
这里首先对 SystemBarConfig 列表根据序号对 SystemBar 进行排序,并将排序后 SystemBar 的 Side 数值保存到 mSystemBarSidesByZOrder 数组中。而该函数是在 SystemBarConfigs 构造函数中进行调用,并且在调用之前还要填充 mSystemBarConfigMap 数据。
SystemBarConfigs
@Inject
public SystemBarConfigs(@Main Resources resources) {
mResources = resources;
// 初始化数据
populateMaps();
// 读取SystemBar所对应的SystemBarConfig的配置信息
readConfigs();
……
// 使用SystemBarConfig的ZOrder属性对SystemBarConfig的Size进行排序
sortSystemBarSidesByZOrder();
}
readConfigs
private void readConfigs() {
mTopNavBarEnabled = mResources.getBoolean(R.bool.config_enableTopSystemBar);
mBottomNavBarEnabled = mResources.getBoolean(R.bool.config_enableBottomSystemBar);
mLeftNavBarEnabled = mResources.getBoolean(R.bool.config_enableLeftSystemBar);
mRightNavBarEnabled = mResources.getBoolean(R.bool.config_enableRightSystemBar);
// 顶部栏可用
if (mTopNavBarEnabled) {
SystemBarConfig topBarConfig =
new SystemBarConfigBuilder()
.setSide(TOP)
// 顶部栏高度
.setGirth(mResources.getDimensionPixelSize(R.dimen.car_top_system_bar_height))
// 系统栏类型
.setBarType(mResources.getInteger(R.integer.config_topSystemBarType))
// 系统栏Z轴序列
.setZOrder(mResources.getInteger(R.integer.config_topSystemBarZOrder))
.setHideForKeyboard(mResources.getBoolean(
R.bool.config_hideTopSystemBarForKeyboard))
.build();
mSystemBarConfigMap.put(TOP, topBarConfig);
}
// 底部栏可用
if (mBottomNavBarEnabled) {
SystemBarConfig bottomBarConfig =
new SystemBarConfigBuilder()
.setSide(BOTTOM)
.setGirth(mResources.getDimensionPixelSize(
R.dimen.car_bottom_system_bar_height))
.setBarType(mResources.getInteger(R.integer.config_bottomSystemBarType))
.setZOrder(
mResources.getInteger(R.integer.config_bottomSystemBarZOrder))
.setHideForKeyboard(mResources.getBoolean(
R.bool.config_hideBottomSystemBarForKeyboard))
.build();
mSystemBarConfigMap.put(BOTTOM, bottomBarConfig);
}
// 左侧栏不可用
if (mLeftNavBarEnabled) {
SystemBarConfig leftBarConfig =
new SystemBarConfigBuilder()
.setSide(LEFT)
.setGirth(mResources.getDimensionPixelSize(
R.dimen.car_left_system_bar_width))
.setBarType(mResources.getInteger(R.integer.config_leftSystemBarType))
.setZOrder(mResources.getInteger(R.integer.config_leftSystemBarZOrder))
.setHideForKeyboard(mResources.getBoolean(
R.bool.config_hideLeftSystemBarForKeyboard))
.build();
mSystemBarConfigMap.put(LEFT, leftBarConfig);
}
// 右侧栏不可用
if (mRightNavBarEnabled) {
SystemBarConfig rightBarConfig =
new SystemBarConfigBuilder()
.setSide(RIGHT)
.setGirth(mResources.getDimensionPixelSize(
R.dimen.car_right_system_bar_width))
.setBarType(mResources.getInteger(R.integer.config_rightSystemBarType))
.setZOrder(mResources.getInteger(R.integer.config_rightSystemBarZOrder))
.setHideForKeyboard(mResources.getBoolean(
R.bool.config_hideRightSystemBarForKeyboard))
.build();
mSystemBarConfigMap.put(RIGHT, rightBarConfig);
}
}
这里首先获取状态了的可用状态,从 config.xml 文件中获取对应数据。
<!-- 配置应该显示哪些系统条 -->
<bool name="config_enableTopSystemBar">true</bool>
<bool name="config_enableLeftSystemBar">false</bool>
<bool name="config_enableRightSystemBar">false</bool>
<bool name="config_enableBottomSystemBar">true</bool>
可以看到,这里配置了状态栏的显示状态,所以修改进度条的显示位置可以通过修改该数据实现。 同样其他相关的配置信息也都可以在对应的配置文件中找到。
3、添加状态栏
我们知道 attachNavBarWindows() 方法最终会循环 mSystemBarSidesByZOrder 集合的内容,用该集合的子项作为参数,依次调用 attachNavBarBySide() 方法。
attachNavBarBySide
private void attachNavBarBySide(int side) {
switch (side) {
case SystemBarConfigs.TOP:
// 如果顶部栏视图容器不为空,将顶部栏视图容器添加到Window中
if (mTopSystemBarWindow != null) {
mWindowManager.addView(mTopSystemBarWindow,
mSystemBarConfigs.getLayoutParamsBySide(SystemBarConfigs.TOP));
}
break;
case SystemBarConfigs.BOTTOM:
if (mBottomSystemBarWindow != null && !mBottomNavBarVisible) {
mBottomNavBarVisible = true;
mWindowManager.addView(mBottomSystemBarWindow,
mSystemBarConfigs.getLayoutParamsBySide(SystemBarConfigs.BOTTOM));
}
break;
case SystemBarConfigs.LEFT:
if (mLeftSystemBarWindow != null) {
mWindowManager.addView(mLeftSystemBarWindow,
mSystemBarConfigs.getLayoutParamsBySide(SystemBarConfigs.LEFT));
}
break;
case SystemBarConfigs.RIGHT:
if (mRightSystemBarWindow != null) {
mWindowManager.addView(mRightSystemBarWindow,
mSystemBarConfigs.getLayoutParamsBySide(SystemBarConfigs.RIGHT));
}
break;
default:
return;
}
}
该方法就是根据对应的 type 判断当前视图容器的具体类型,到底是顶部栏、底部栏、左侧栏还是右侧栏,根据类型配合类型相对应的参数将该视图容器添加到 WindowManager 中。
二、状态栏配置
状态栏配置类 SystemBarConfig 为 SystemBarConfigs 的内部类。
1、SystemBarConfig
// 系统条将开始出现在HUN的顶部的z轴顺序
private static final int HUN_ZORDER = 10;
private static final int[] BAR_TYPE_MAP = {
InsetsState.ITYPE_STATUS_BAR, // 状态栏对应的系统装饰窗口类型
InsetsState.ITYPE_NAVIGATION_BAR, // 导航栏对应的系统装饰窗口类型
InsetsState.ITYPE_CLIMATE_BAR, // 左侧栏对应的系统装饰窗口类型
InsetsState.ITYPE_EXTRA_NAVIGATION_BAR // 右侧栏对应的系统装饰窗口类型
private static final class SystemBarConfig {
private final int mSide;
private final int mBarType;
private final int mGirth;
private final int mZOrder;
private final boolean mHideForKeyboard;
private int[] mPaddings = new int[]{0, 0, 0, 0};
private SystemBarConfig(@SystemBarSide int side, int barType, int girth, int zOrder,
boolean hideForKeyboard) {
mSide = side;
mBarType = barType;
mGirth = girth;
mZOrder = zOrder;
mHideForKeyboard = hideForKeyboard;
}
private int getSide() {
return mSide;
}
private int getBarType() {
return mBarType;
}
private int getGirth() {
return mGirth;
}
private int getZOrder() {
return mZOrder;
}
private boolean getHideForKeyboard() {
return mHideForKeyboard;
}
private int[] getPaddings() {
return mPaddings;
}
private WindowManager.LayoutParams getLayoutParams() {
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
isHorizontalBar(mSide) ? ViewGroup.LayoutParams.MATCH_PARENT : mGirth,
isHorizontalBar(mSide) ? mGirth : ViewGroup.LayoutParams.MATCH_PARENT,
mapZOrderToBarType(mZOrder),
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
| WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
PixelFormat.TRANSLUCENT); // 设置窗口半透明(全透明:TRANSPARENT)
lp.setTitle(BAR_TITLE_MAP.get(mSide));
//顶部栏为new int[]{InsetsState.ITYPE_STATUS_BAR, InsetsState.ITYPE_TOP_MANDATORY_GESTURES}
//底部栏为new int[]{InsetsState.ITYPE_NAVIGATION_BAR, InsetsState.ITYPE_BOTTOM_MANDATORY_GESTURES}
//providesInsetsTypes这个字段很重要,只有设置对这个字段,系统才会认定该窗口是对应的装饰窗口
lp.providesInsetsTypes = new int[]{BAR_TYPE_MAP[mBarType], BAR_GESTURE_MAP.get(mSide)};
lp.setFitInsetsTypes(0);
lp.windowAnimations = 0;
lp.gravity = BAR_GRAVITY_MAP.get(mSide);
return lp;
}
private int mapZOrderToBarType(int zOrder) {
// 顶部栏窗口类型为TYPE_STATUS_BAR_ADDITIONAL,底部栏TYPE_NAVIGATION_BAR_PANEL
return zOrder >= HUN_ZORDER ? WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL
: WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL;
}
private void setPaddingBySide(@SystemBarSide int side, int padding) {
mPaddings[side] = padding;
}
}
这里主要用来配置状态栏类型及对应的视图内容,其中状态栏位置和标题等信息是在上面的 populateMaps() 方法中赋值。
populateMaps
public static final int TOP = 0;
public static final int BOTTOM = 1;
public static final int LEFT = 2;
public static final int RIGHT = 3;
private static void populateMaps() {
// 将系统栏位置与Gravity值关联
BAR_GRAVITY_MAP.put(TOP, Gravity.TOP);
BAR_GRAVITY_MAP.put(BOTTOM, Gravity.BOTTOM);
BAR_GRAVITY_MAP.put(LEFT, Gravity.LEFT);
BAR_GRAVITY_MAP.put(RIGHT, Gravity.RIGHT);
// 将系统栏位置与标题字符串关联
BAR_TITLE_MAP.put(TOP, "TopCarSystemBar");
BAR_TITLE_MAP.put(BOTTOM, "BottomCarSystemBar");
BAR_TITLE_MAP.put(LEFT, "LeftCarSystemBar");
BAR_TITLE_MAP.put(RIGHT, "RightCarSystemBar");
// 将系统栏位置与手势类型关联
BAR_GESTURE_MAP.put(TOP, InsetsState.ITYPE_TOP_MANDATORY_GESTURES);
BAR_GESTURE_MAP.put(BOTTOM, InsetsState.ITYPE_BOTTOM_MANDATORY_GESTURES);
BAR_GESTURE_MAP.put(LEFT, InsetsState.ITYPE_LEFT_MANDATORY_GESTURES);
BAR_GESTURE_MAP.put(RIGHT, InsetsState.ITYPE_RIGHT_MANDATORY_GESTURES);
}
2、SystemBarConfigBuilder
private static final class SystemBarConfigBuilder {
private int mSide;
private int mBarType;
private int mGirth;
private int mZOrder;
private boolean mHideForKeyboard;
private SystemBarConfigBuilder setSide(@SystemBarSide int side) {
mSide = side;
return this;
}
private SystemBarConfigBuilder setBarType(int type) {
mBarType = type;
return this;
}
private SystemBarConfigBuilder setGirth(int girth) {
mGirth = girth;
return this;
}
private SystemBarConfigBuilder setZOrder(int zOrder) {
mZOrder = zOrder;
return this;
}
private SystemBarConfigBuilder setHideForKeyboard(boolean hide) {
mHideForKeyboard = hide;
return this;
}
private SystemBarConfig build() {
return new SystemBarConfig(mSide, mBarType, mGirth, mZOrder, mHideForKeyboard);
}
}
SystemBarConfigBuilder 同样是 SystemBarConfigs 的内部类,它实现了构建者模式(Builder Pattern),用于简化 SystemBarConfig 对象的创建。
原文地址:https://blog.csdn.net/c19344881x/article/details/145011047
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!