Android 9.0 车载SystemUI 自定义 Statusbar 和 Navigationbar

颜经艺
2023-12-01

Android 9.0 车载SystemUI 自定义 Statusbar 和 Navigationbar

一、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生命周期,横竖屏布局会报空指针异常。
		
    }
}
 类似资料: