IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 定制安卓9.0的状态栏和导航栏 -> 正文阅读

[移动开发]定制安卓9.0的状态栏和导航栏

一、定制状态栏

1、SystemUIApplication启动SystemUI组件的关键代码

framework/base/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java

public class SystemUIApplication extends Application implements SysUiServiceProvider {
  public void startServicesIfNeeded() {
        String[] names = getResources().getStringArray(R.array.config_systemUIServiceComponents);
        startServicesIfNeeded(names);
    }
    private void startServicesIfNeeded(String[] services) {
        mServices = new SystemUI[services.length];
        final int N = services.length;
        for (int i = 0; i < N; i++) {
            String clsName = services[i];//具体系统组件类的完整路径
            Class cls = Class.forName(clsName);
            mServices[i] = (SystemUI) cls.newInstance();//通过反射创建实例对象
            mServices[i].start(); //调用start()启动
        }
    }
}

frameworks/base/packages/SystemUI/res/values/config.xml

    <string-array name="config_systemUIServiceComponents" translatable="false">
        <item>com.android.systemui.Dependency</item>
        <item>com.android.systemui.util.NotificationChannels</item>
        <item>com.android.systemui.statusbar.CommandQueue$CommandQueueStart</item>
        <item>com.android.systemui.keyguard.KeyguardViewMediator</item>
        <item>com.android.systemui.recents.Recents</item>
        <item>com.android.systemui.volume.VolumeUI</item>
        <item>com.android.systemui.stackdivider.Divider</item>
        <item>com.android.systemui.SystemBars</item>
        <item>com.android.systemui.usb.StorageNotification</item>
        <item>com.android.systemui.power.PowerUI</item>
        <item>com.android.systemui.media.RingtonePlayer</item>
        <item>com.android.systemui.keyboard.KeyboardUI</item>
        <item>com.android.systemui.pip.PipUI</item>
        <item>com.android.systemui.shortcut.ShortcutKeyDispatcher</item>
        <item>@string/config_systemUIVendorServiceComponent</item>
        <item>com.android.systemui.util.leak.GarbageMonitor$Service</item>
        <item>com.android.systemui.LatencyTester</item>
        <item>com.android.systemui.globalactions.GlobalActionsComponent</item>
        <item>com.android.systemui.ScreenDecorations</item>
        <item>com.android.systemui.fingerprint.FingerprintDialogImpl</item>
        <item>com.android.systemui.SliceBroadcastRelayHandler</item>
    </string-array>

2、SystemBars启动StatusBar组件关键代码

frameworks/base/packages/SystemUI/src/com/android/systemui/SystemBars.java

public class SystemBars extends SystemUI {
 	...
    @Override
    public void start() {
        createStatusBarFromConfig();//通过配置创建系统状态栏
    }
	
   private void createStatusBarFromConfig() {
      final String clsName = mContext.getString(R.string.config_statusBarComponent);//获取系统状态栏对应类的全路径
      Class<?> cls = mContext.getClassLoader().loadClass(clsName);//加载对应的类对象
      mStatusBar = (SystemUI) cls.newInstance();//通过反射创建实例对象
      mStatusBar.mContext = mContext;
      mStatusBar.mComponents = mComponents;
      mStatusBar.start();//调用系统状态栏的start方法
  }

frameworks/base/packages/SystemUI/res/values/config.xml

<string name="config_statusBarComponent">com.android.systemui.statusbar.phone.StatusBar</string>

3、StatusBar加载布局文件super_status_bar.xml的关键代码

frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java

public class StatusBar extends SystemUI implements DemoMode,
        DragDownHelper.DragDownCallback, ActivityStarter, OnUnlockMethodChangedListener,
        OnHeadsUpChangedListener, CommandQueue.Callbacks, ZenModeController.Callback,
        ColorExtractor.OnColorsChangedListener, ConfigurationListener, NotificationPresenter {

    protected StatusBarWindowView mStatusBarWindow;//状态栏窗口
    protected PhoneStatusBarView mStatusBarView;//手机状态栏视图

    @Override
    public void start() {
        createAndAddWindows(); //创建整个SystemUI视图并添加到WindowManager中
    }
    public void createAndAddWindows() {
        addStatusBarWindow();
    }
    private void addStatusBarWindow() {
        makeStatusBarView(); //创建整个SystemUI视图
    }
    //构建组件视图
   protected void makeStatusBarView() {
        final Context context = mContext;
        //实例化整个SystemUI视图,包括状态栏,通知面版,锁屏
        inflateStatusBarWindow(context);
        ...
        //实例化状态栏视图
        FragmentHostManager.get(mStatusBarWindow)
        .addTagListener(CollapsedStatusBarFragment.TAG, (tag, fragment) -> {})
        .getFragmentManager()
        .beginTransaction()
        //这里和id为status_bar_container的FrameLayout控件进行关联
        .replace(R.id.status_bar_container, new CollapsedStatusBarFragment(), CollapsedStatusBarFragment.TAG)
        .commit();
        ...        
    }
    
    protected void inflateStatusBarWindow(Context context) {
    	//实例化整个SystemUI视图,包括状态栏,通知面版,锁屏
        mStatusBarWindow = (StatusBarWindowView) View.inflate(context, R.layout.super_status_bar, null);
    }
    
}

frameworks/base/packages/SystemUI/res/layout/super_status_bar.xml

<?xml version="1.0" encoding="utf-8"?>
<com.android.systemui.statusbar.phone.StatusBarWindowView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:sysui="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:tools="http://schemas.android.com/tools"
    tools:background="#FFFFFF"
    android:fitsSystemWindows="true">
	<!--状态栏视图容器控件-->
    <FrameLayout
        android:id="@+id/status_bar_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</com.android.systemui.statusbar.phone.StatusBarWindowView>

4、CollapsedStatusBarFragment加载状态栏布局文件status_bar.xml的关键代码

framework/base/package/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java

public class CollapsedStatusBarFragment extends Fragment implements CommandQueue.Callbacks {
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
                             Bundle savedInstanceState) {
        return inflater.inflate(R.layout.status_bar, container, false);
    }
}

framework/base/package/SystemUI/res/layout/status_bar.xml

<?xml version="1.0" encoding="utf-8"?><!--
<com.android.systemui.statusbar.phone.PhoneStatusBarView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/status_bar"
    android:layout_width="match_parent"
    android:layout_height="@dimen/status_bar_height"
    android:accessibilityPaneTitle="@string/status_bar"
    android:background="@drawable/system_bar_background"
    android:descendantFocusability="afterDescendants"
    android:focusable="false"
    android:orientation="vertical">

    <ImageView
        android:id="@+id/notification_lights_out"
        android:layout_width="@dimen/status_bar_icon_size"
        android:layout_height="match_parent"
        android:paddingStart="@dimen/status_bar_padding_start"
        android:paddingBottom="2dip"
        android:scaleType="center"
        android:src="@drawable/ic_sysbar_lights_out_dot_small"
        android:visibility="gone"
        tools:visibility="visible" />

    <LinearLayout
        android:id="@+id/status_bar_contents"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal"
        android:paddingStart="@dimen/status_bar_padding_start"
        android:paddingEnd="@dimen/status_bar_padding_end">

        <ViewStub
            android:id="@+id/operator_name"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout="@layout/operator_name" />

        <FrameLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1">

            <include layout="@layout/heads_up_status_bar_layout" />

            <LinearLayout
                android:id="@+id/status_bar_left_side"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:clipChildren="false">

                <com.android.systemui.statusbar.policy.Clock
                    android:id="@+id/clock"
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:gravity="center_vertical|start"
                    android:paddingStart="@dimen/status_bar_left_clock_starting_padding"
                    android:paddingEnd="@dimen/status_bar_left_clock_end_padding"
                    android:singleLine="true"
                    android:textAppearance="@style/TextAppearance.StatusBar.Clock" />

                <com.android.systemui.statusbar.AlphaOptimizedFrameLayout
                    android:id="@+id/notification_icon_area"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:clipChildren="false"
                    android:orientation="horizontal" />

            </LinearLayout>
        </FrameLayout>

  
        <android.widget.Space
            android:id="@+id/cutout_space_view"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:gravity="center_horizontal|center_vertical" />

        <com.android.keyguard.AlphaOptimizedLinearLayout
            android:id="@+id/system_icon_area"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:gravity="center_vertical|end"
            android:orientation="horizontal">

            <include layout="@layout/system_icons" />
        </com.android.keyguard.AlphaOptimizedLinearLayout>
    </LinearLayout>

    <ViewStub
        android:id="@+id/emergency_cryptkeeper_text"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout="@layout/emergency_cryptkeeper_text" />

</com.android.systemui.statusbar.phone.PhoneStatusBarView>

二、定制导航栏

1、StatusBar创建导航栏

frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java

public class StatusBar extends SystemUI implements DemoMode,
        DragDownHelper.DragDownCallback, ActivityStarter, OnUnlockMethodChangedListener,
        OnHeadsUpChangedListener, CommandQueue.Callbacks, ZenModeController.Callback,
        ColorExtractor.OnColorsChangedListener, ConfigurationListener, NotificationPresenter {
        
    private NavigationBarFragment mNavigationBar;//导航栏所在的Fragment
    private View mNavigationBarView;//导航栏视图
    
    //构建组件视图
    protected void makeStatusBarView() {	
   		   ...	
           boolean showNav = mWindowManagerService.hasNavigationBar();
           if (showNav) {
           		//创建导航栏
               createNavigationBar();
           }
   		   ...	           
   }   
  protected void createNavigationBar() {
        mNavigationBarView = NavigationBarFragment.create(mContext, (tag, fragment) -> {
            mNavigationBar = (NavigationBarFragment) fragment;
            if (mLightBarController != null) {
                mNavigationBar.setLightBarController(mLightBarController);
            }
            mNavigationBar.setCurrentSysuiVisibility(mSystemUiVisibility);
        });
    }     

2、NavigationBarFragment加载状态栏布局文件status_bar.xml的关键代码

frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java

public class NavigationBarFragment extends Fragment implements Callbacks {
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
                             Bundle savedInstanceState) {
        return inflater.inflate(R.layout.navigation_bar, container, false);
    }
}    

framework/base/package/SystemUI/res/layout/navigation_bar.xml

<?xml version="1.0" encoding="utf-8"?>
<com.android.systemui.statusbar.phone.NavigationBarView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:systemui="http://schemas.android.com/apk/res-auto"
    android:layout_height="match_parent"
    android:layout_width="match_parent"
    android:background="@drawable/system_bar_background">

    <com.android.systemui.statusbar.phone.NavigationBarInflaterView
        android:id="@+id/navigation_inflater"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</com.android.systemui.statusbar.phone.NavigationBarView>

三、车载导航栏

1.1、车载状态栏类所对应的关键代码

com.android.systemui.statusbar.car.CarStatusBar.java


public class CarStatusBar extends StatusBar implements
        CarBatteryController.BatteryViewHandler {

	...
	//创建底部导航栏
    @Override
    protected void createNavigationBar() {
        mShowBottom = mContext.getResources().getBoolean(R.bool.config_enableBottomNavigationBar);
   		...
        buildNavBarWindows();
        buildNavBarContent();
        attachNavBarWindows();
    }

	//构建底部导航栏
    private void buildNavBarWindows() {
        if (mShowBottom) {
             mNavigationBarWindow = (ViewGroup) View.inflate(mContext,
                    R.layout.navigation_bar_window, null);
        }
        ...
    }

	//构建底部导航栏的内容
    private void buildNavBarContent() {
        if (mShowBottom) {
            buildBottomBar((mDeviceIsProvisioned) ? R.layout.car_navigation_bar :
                    R.layout.car_navigation_bar_unprovisioned);
        }
        ...
    }
    private void buildBottomBar(int layout) {
        View.inflate(mContext, layout, mNavigationBarWindow);
        mNavigationBarView = (CarNavigationBarView) mNavigationBarWindow.getChildAt(0);
        mNavigationBarView.setStatusBar(this);
    }

	//将导航栏添加到Window中
    private void attachNavBarWindows() {
        if (mShowBottom) {
            WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                    LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
                    WindowManager.LayoutParams.TYPE_NAVIGATION_BAR,
                    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("CarNavigationBar");
            lp.windowAnimations = 0;
            mWindowManager.addView(mNavigationBarWindow, lp);
        }
    }

    @Override
    public void destroy() {
  		...
        if (mNavigationBarWindow != null) {
            mWindowManager.removeViewImmediate(mNavigationBarWindow);
            mNavigationBarView = null;
        }
  		...        
   }     

	...

    @Override
    public View getNavigationBarWindow() {
        return mNavigationBarWindow;
    }

}

1.2、车载状态栏所对应的布局文件

framework/base/package/SystemUI/res/layout/navigation_bar_window.xml

<com.android.systemui.statusbar.phone.NavigationBarFrame
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:systemui="http://schemas.android.com/apk/res-auto"
    android:id="@+id/navigation_bar_frame"
    android:layout_height="match_parent"
    android:layout_width="match_parent">

</com.android.systemui.statusbar.phone.NavigationBarFrame>

2.1、车载导航栏所对应的类的关键代码

com.android.systemui.statusbar.car.CarNavigationBarView

class CarNavigationBarView extends LinearLayout {
    private View mNavButtons;
    private AlphaOptimizedImageButton mNotificationsButton;
    private CarStatusBar mCarStatusBar;
    private Context mContext;
    private View mLockScreenButtons;

    public CarNavigationBarView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
    }

    @Override
    public void onFinishInflate() {
        mNavButtons = findViewById(R.id.nav_buttons);
        mLockScreenButtons = findViewById(R.id.lock_screen_nav_buttons);

        mNotificationsButton = findViewById(R.id.notifications);
        if (mNotificationsButton != null) {
            mNotificationsButton.setOnClickListener(this::onNotificationsClick);
        }
        View mStatusIcons = findViewById(R.id.statusIcons);
        if (mStatusIcons != null) {
            // Attach the controllers for Status icons such as wifi and bluetooth if the standard
            // container is in the view.
            StatusBarIconController.DarkIconManager mDarkIconManager =
                    new StatusBarIconController.DarkIconManager(
                            mStatusIcons.findViewById(R.id.statusIcons));
            mDarkIconManager.setShouldLog(true);
            Dependency.get(StatusBarIconController.class).addIconGroup(mDarkIconManager);
        }

    }

    void setStatusBar(CarStatusBar carStatusBar) {
        mCarStatusBar = carStatusBar;
    }

    protected void onNotificationsClick(View v) {
        mCarStatusBar.togglePanel();
    }

    /**
     * If there are buttons declared in the layout they will be shown and the normal
     * Nav buttons will be hidden.
     */
    public void showKeyguardButtons() {
        if (mLockScreenButtons == null) {
            return;
        }
        mLockScreenButtons.setVisibility(View.VISIBLE);
        mNavButtons.setVisibility(View.GONE);
    }

    /**
     * If there are buttons declared in the layout they will be hidden and the normal
     * Nav buttons will be shown.
     */
    public void hideKeyguardButtons() {
        if (mLockScreenButtons == null) {
            return;
        }
        mNavButtons.setVisibility(View.VISIBLE);
        mLockScreenButtons.setVisibility(View.GONE);
    }
}

2.2、车载导航栏所对应的布局文件

framework/base/package/SystemUI/res/layout/navigation_bar_window.xml

<com.android.systemui.statusbar.car.CarNavigationBarView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_height="match_parent"
    android:layout_width="match_parent"
    android:background="@drawable/system_bar_background">

    <!-- phone.NavigationBarView has rot0 and rot90 but we expect the car head unit to have a fixed
         rotation so skip this level of the heirarchy.
    -->
    <LinearLayout
        android:layout_height="match_parent"
        android:layout_width="match_parent"
        android:orientation="horizontal"
        android:clipChildren="false"
        android:clipToPadding="false"
        android:id="@+id/nav_buttons"
        android:animateLayoutChanges="true">

        <!-- Buttons get populated here from a car_arrays.xml. -->
    </LinearLayout>

    <!-- lights out layout to match exactly -->
    <LinearLayout
        android:layout_height="match_parent"
        android:layout_width="match_parent"
        android:orientation="horizontal"
        android:id="@+id/lights_out"
        android:visibility="gone">
        <!-- Must match nav_buttons. -->
    </LinearLayout>

</com.android.systemui.statusbar.car.CarNavigationBarView>
  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-09-13 11:27:25  更:2022-09-13 11:31:28 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 5:26:28-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码