一、Android9.0 Car statusbar 默认显示的是CarStatusBar在
com/android/systemui/SystemBars.java—>createStatusBarFromConfig()
private void createStatusBarFromConfig() {
if (DEBUG) Log.d(TAG, "createStatusBarFromConfig");
final String clsName = mContext.getString(R.string.config_statusBarComponent);
if (clsName == null || clsName.length() == 0) {
throw andLog("No status bar component configured", null);
}
Class<?> cls = null;
try {
cls = mContext.getClassLoader().loadClass(clsName);
} catch (Throwable t) {
throw andLog("Error loading status bar component: " + clsName, t);
}
try {
mStatusBar = (SystemUI) cls.newInstance();
} catch (Throwable t) {
throw andLog("Error creating status bar component: " + clsName, t);
}
......
mStatusBar.start();
}
二、我们需要在value/config文件中修改config_statusBarComponent,改成自己自定义的StatusBar在SystemUI目录value/config中找到config_statusBarComponent并且修改,编译,push发现还是CarStatusBar没有发生变化,于是去其他目录下查找config_statusBarComponent,发现在packages/services/Car/car_product/overlay/frameworks/base/packages/SystemUI/res/values也有定义,修改后重新编译变成自定义的statusbar,为什么修改SystemUI下config不生效呢?看了下packages.services.Car.car_product.build中car_base.mk有这样的定义PRODUCT_PACKAGE_OVERLAYS += packages/services/Car/car_product/overlay 会覆盖相同目录下的资源文件,有兴趣更深入了解的可以Android Overlay机制。
packages/services/Car/car_product/overlay/frameworks/base/packages/SystemUI/res/values
<string name="config_statusBarComponent" translatable="false">com.android.systemui.statusbar.Ax.AxStatusBar</string>
三、com.android.systemui.statusbar.Ax
AxStatusbarView.java自定义LinearLayout加载R.layout.ax_status_bar_view,布局根据自己需求,这里就不贴了。
public class AxStatusbarView extends LinearLayout {
private String TAG = "AxStatusBarView";
private Context mContext;
private LinearLayout mLayout_mobile_signal;
private LinearLayout ll_right;
private LinearLayout ll_left;
private StatusBar mBar;
public AXStatusbarView(Context context) {
super(context);
mContext = context;
LayoutInflater.from(context).inflate(R.layout.ax_status_bar_view, this);
}
public AxStatusbarView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
LayoutInflater.from(context).inflate(R.layout.ax_status_bar_view, this);
}
public AxStatusbarView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContext = context;
LayoutInflater.from(context).inflate(R.layout.ax_status_bar_view, this);
}
public void setBar(StatusBar bar) {
mBar = bar;
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mLayout_mobile_signal = findViewById(R.id.layout_mobile_signal);
ll_right = findViewById(R.id.ll_right);
ll_left = findViewById(R.id.ll_left);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
}
}
四、在SystemUI/res/layout/status_bar.xml 中添加自定义AxStatusbarView
五、com/android/systemui/statusbar/phone/PhoneStatusBarView.java
public class PhoneStatusBarView extends PanelBar {
private AXStatusbarView mAXStatusbarView;
public void setBar(StatusBar bar) {
mBar = bar;
mAXStatusbarView.setBar(mBar);
}
@Override
public void onFinishInflate() {
mBarTransitions.init();
mBattery = findViewById(R.id.battery);
mCutoutSpace = findViewById(R.id.cutout_space_view);
///xza:add custom statusbar
mAXStatusbarView = findViewById(R.id.ax_status_bar_view);
updateResources();
}
}
三、看下自定义AxStatusBar.java,主要做了加载自定义AxNavigationBarView,R.layout.navigation_bar_window根据自己的需要添加布局文件,这里不贴代码了
public class AxStatusBar extends StatusBar {
private ViewGroup mNavigationBarWindow;
//自定义NavigationbarView,代码后面会加上
private AxNavigationBarView mNavigationBarView;
private WindowManager.LayoutParams lp;
@Override
public void destroy() {
if (mNavigationBarWindow != null) {
mWindowManager.removeViewImmediate(mNavigationBarWindow);
mNavigationBarView = null;
}
super.destroy();
}
@Override
protected void makeStatusBarView() {
super.makeStatusBarView();
FragmentHostManager manager = FragmentHostManager.get(mStatusBarWindow);
mStatusBarWindow.setVisibility(View.VISIBLE);
@Override
protected void createNavigationBar() {
buildNavBarWindows();
}
private void buildNavBarWindows() {
if (mNavigationBarView != null) {
return;
}
mNavigationBarWindow = (ViewGroup) View.inflate(mContext,
R.layout.navigation_bar_window, null);
if (mNavigationBarWindow == null) {
Log.e(TAG, "AxStatusbar failed inflate for R.layout.navigation_bar_window");
}
View.inflate(mContext, R.layout.ax_navigation_bar, mNavigationBarWindow);
mNavigationBarView = (AxNavigationBarView) mNavigationBarWindow.getChildAt(0);
if (mNavigationBarView == null) {
Log.e(TAG, "AxStatusbar failed inflate for R.layout.ax_navigation_bar");
}
mNavigationBarView.setBackground(null);
mNavigationBarView.setBackgroundResource(R.mipmap.navigation_bar_bg);
mNavigationBarView.getBarTransitions().setAlwaysOpaque(false);
lp = new WindowManager.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.TYPE_NAVIGATION_BAR,
WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
| WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
PixelFormat.TRANSLUCENT);
lp.setTitle("AxNavigationBar");
lp.windowAnimations = 0;
Log.i(TAG, "is navigationbar window attached "+mNavigationBarWindow.isAttachedToWindow());
mStatusBarWindow.setVisibility(View.VISIBLE);
mWindowManager.addView(mNavigationBarWindow, lp);
mNavigationBarWindow.invalidate();
}
@Override
public NavigationBarView getNavigationBarView() {
return mNavigationBarView;
}
@Override
public NavigationBarView getNavigationBarView() {
return mNavigationBarView;
}
}
七、AxNavigationBarView
public class AxNavigationBarView extends NavigationBarView {
public AxNavigationBarView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
mStatusBar = SysUiServiceProvider.getComponent(context, StatusBar.class);
Log.d("xza", "get connectToCarService");
@Override
public void onFinishInflate() {
//初始化view这边不贴代码了
}
@Override
public View getCurrentView() {
return this;
}
@Override
public void reorient() {
//需要重写父类NavigationBarView方法
//不然会进入父类reorient()——>updateCurrentView();因为自定义navigationbar,
//没有走NavigationBarFragment生命周期,横竖屏布局会报空指针异常。
}
}