admin 管理员组

文章数量: 1184232

修改主页布局

概述

​ 在 Android 操作系统中,Launcher (主页应用)是用户与设备交互的核心界面之一,它负责 显示应用程序列表、提供快捷方式、管理小部件 等功能。其中,Launcher3 是 Android 系统 默认的启动器 应用程序,我们可以通过修改Launcher3的源码,来改变主页应用的样式和布局。下面将结合源码,分析如何修改Launcher3主页的相关样式和布局。

布局构成

​ Launcher3最核心的类是一个 Launcher.java (可以看作是Launcher中的MainActivity),基本上所有操作(包括UI的定制)都集中在这个Activity上。在Launcher.java 中,通过setContentView()设置的布局参数是R.layout.launcher,对应的是launcher.xml文件,它定义了启动器界面的整体结构和组件的位置,我们看下这个布局文件里的内容:

<?xml version="1.0" encoding="utf-8"?><com.android.launcher3.LauncherRootViewxmlns:android=""xmlns:launcher=""android:id="@+id/launcher"android:layout_width="match_parent"android:layout_height="match_parent"android:fitsSystemWindows="true"><com.android.launcher3.dragndrop.DragLayerandroid:id="@+id/drag_layer"android:layout_width="match_parent"android:layout_height="match_parent"android:clipChildren="false"android:clipToPadding="false"android:importantForAccessibility="no"><com.android.launcher3.views.AccessibilityActionsViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:contentDescription="@string/home_screen"/><!-- The workspace contains 5 screens of cells --><!-- DO NOT CHANGE THE ID --><com.android.launcher3.Workspaceandroid:id="@+id/workspace"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_gravity="center"android:theme="@style/HomeScreenElementTheme"launcher:pageIndicator="@+id/page_indicator"/><!-- DO NOT CHANGE THE ID --><includeandroid:id="@+id/hotseat"layout="@layout/hotseat"/><!-- Keep these behind the workspace so that they are not visible when
         we go into AllApps --><com.android.launcher3.pageindicators.WorkspacePageIndicatorandroid:id="@+id/page_indicator"android:layout_width="match_parent"android:layout_height="@dimen/workspace_page_indicator_height"android:layout_gravity="bottom|center_horizontal"android:theme="@style/HomeScreenElementTheme"/><includeandroid:id="@+id/drop_target_bar"layout="@layout/drop_target_bar"/><com.android.launcher3.views.ScrimViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:id="@+id/scrim_view"android:background="@android:color/transparent"/><includeandroid:id="@+id/apps_view"layout="@layout/all_apps"android:layout_width="match_parent"android:layout_height="match_parent"/><includeandroid:id="@+id/overview_panel"layout="@layout/overview_panel"/></com.android.launcher3.dragndrop.DragLayer></com.android.launcher3.LauncherRootView>

​ 由上面内容可以看到,Launcher3,父布局是一个自定义的LauncherRootView,在这个LauncherRootView中只有一个子布局DragLayer,在DragLayer中放置了Workspace、Hotseat、WorkspacePageIndicator等内容。这里我们先看下Launcher3主页的构造图,以便我们了解各个子布局的相关内容:

  • Launcher3布局的最外面是一个自定义的View: LauncherRootView ,它是继承自 FrameLayout ;LauncherRootView里面只有一个叫 DragLayer 的ViewGroup,它同样继承自FrameLayout,主要功能就是 处理拖拽事件 ,当你在拖拽一个图标的时候,就相当于是一个view放到了DragLayer里面,这个view会跟随你的手在屏幕上移动。
  • 屏幕上可以左右滑动的整个页面叫做 Workspace ,Workspace的父类是 PagedView ,PagedViewk用来处理左右滑动。
  • Workspace里面可能含有多个页面(屏),多个页面存在时,可以左右滑动来切换页面;可以滑动的单独一屏就是一个 CellLayout ,CellLayout负责自己页面图标和小部件的显示和整齐摆放。
  • 在左右滑动屏幕切换页面时 屏幕最下方会出现的指示器 PageIndicator (一般是几个小圆点,这里图示中被隐藏了),告诉你桌面有几屏,当前在哪一屏上(圆点会高亮)。
  • 在Workspace中,向上滑动屏幕可以唤出所有应用列表(抽屉样式),向下滑动可以唤出状态栏和通知栏。
  • 在CellLayout中可以放置 组件 应用 包含应用的文件夹 等。如上图中顶部的搜索框就是谷歌提供的原生搜索框(其实它并不算一个组件,而是一个特殊元素),屏幕靠下方的左右两边分别是应用文件夹和单个应用图标。当 长按 CellLayout上的组件、应用、文件夹或者空白地方的时候,会出现一个MENU菜单,可以对组件或应用进行配置,或者添加组件等。当长按组件、应用或文件夹,并拖动到屏幕上方时,屏幕上方会显示一个DropTargetBar区域,里面有“移除”按钮,可以对组件进行移除,对app进行卸载等操作。
  • 底部有五个固定不动的图标所在的区域叫做Hotseat,用来放置比较常用的应用,比如拨号,短信,相机等。
  • 底部右侧有三个白色按钮的区域是导航栏。导航栏可以在所有页面中常显,用于全局控制(返回、回到主页、最近应用)。

这里简单展示下几个控件的布局代码:

hotseat.xml

<com.android.launcher3.Hotseatxmlns:android=""xmlns:launcher=""android:id="@+id/hotseat"android:layout_width="match_parent"android:layout_height="match_parent"android:theme="@style/HomeScreenElementTheme"android:importantForAccessibility="no"android:preferKeepClear="true"launcher:containerType="hotseat"/>

all_apps.xml

<com.android.launcher3.allapps.LauncherAllAppsContainerViewxmlns:android=""android:id="@+id/apps_view"android:layout_width="match_parent"android:layout_height="match_parent"android:clipChildren="true"android:clipToPadding="false"android:focusable="false"android:saveEnabled="false"/>

drop_target_bar.xml

<com.android.launcher3.DropTargetBarxmlns:android=""android:layout_width="match_parent"android:layout_height="@dimen/dynamic_grid_drop_target_size"android:layout_gravity="center_horizontal|top"android:focusable="false"android:alpha="0"android:theme="@style/HomeScreenElementTheme"android:visibility="invisible"><!-- Delete target --><com.android.launcher3.DeleteDropTargetandroid:id="@+id/delete_target_text"style="@style/DropTargetButton"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:gravity="center"android:text="@string/remove_drop_target_label"/><!-- Uninstall target --><com.android.launcher3.SecondaryDropTargetandroid:id="@+id/uninstall_target_text"style="@style/DropTargetButton"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:gravity="center"android:text="@string/uninstall_drop_target_label"/></com.android.launcher3.DropTargetBar>

上面这三个控件都是直接include在Launcher.xml的布局中的,其他子布局也是以类似于自定义View的形式被添加到Launcher.xml中的,比如workspace:

<com.android.launcher3.Workspaceandroid:id="@+id/workspace"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_gravity="center"android:theme="@style/HomeScreenElementTheme"launcher:pageIndicator="@+id/page_indicator"/>

Workspace.java是在Launcher的onCreate()阶段被创建并添加到主页里面的:

// Launcher3/src/com/android/launcher3/Launcher.java@ThunkWorkspace<?> mWorkspace;@ThunkDragLayer mDragLayer;@Override@TargetApi(Build.VERSION_CODES.S)protectedvoidonCreate(Bundle savedInstanceState){
   
   // ...setupViews();// ...}protectedvoidsetupViews(){
   
   inflateRootView(R.layout.launcher);
    mDragLayer =findViewById(R.id.drag_layer);
    mFocusHandler = mDragLayer.getFocusIndicatorHelper();// 绑定workspace
    mWorkspace = mDragLayer.findViewById(R.id.workspace);// workspace做一些初始化的工作
    mWorkspace.initParentViews(mDragLayer);
    mOverviewPanel =findViewById(R.id.overview_panel);
    mHotseat =findViewById(R.id.hotseat);
    mHotseat.setWorkspace(mWorkspace);
    mDragLayer.setup(mDragController, mWorkspace);
    mWorkspace.setup(mDragController);
    mWorkspace.lockWallpaperToDefaultPage();
    mWorkspace.bindAndInitFirstWorkspaceScreen();
    mDragController.addDragListener(mWorkspace);// ...}

​ 各子布局的添加和加载就不展开介绍了,这里先介绍一个Launcher3很重要的内容: DeviceProfile.java和device_profiles.xml

DeviceProfile

DeviceProfile.java 包含了多个用于描述设备配置的属性,例如 mNumColumns (列数)、 mNumRows (行数)、 mHotseatHeight (Dock的高度)、 mIconSizePx (图标大小)等,这些属性用于确定Launcher的布局和各个组件的位置。 DeviceProfile Launcher 启动时被创建,并根据设备的实际配置(device_profiles.xml)进行初始化。

  • 初始化过程中会根据设备的屏幕尺寸、方向等因素计算出各种关键属性。
  • 当设备的配置发生变化时(例如旋转屏幕), DeviceProfile 会被更新以反映新的配置。
  • 更新过程中会重新计算关键属性,并通知Launcher的各个组件进行相应的调整。

device_profiles.xml 是一个XML配置文件,位于Launcher3项目的 res/xml 目录下。它定义了一系列设备配置,每种配置对应着不同的屏幕尺寸、方向和密度等信息,这一系列配置用于在不同设备上适配Launcher。这样可以确保Launcher在不同设备上都能够良好地显示和运行。
​ 当Launcher启动时,它会被DeviceProfile.java动态加载,并根据当前设备的实际配置找到最合适的预设配置,这些预设配置【 mNumColumns (列数)、 mNumRows (行数)、 mIconSizePx (图标大小)等】用于 初始化 DeviceProfile 对象 。【各属性的介绍放到下一小节中了】

下面简单介绍下DeviceProfile.java和device_profiles.xml的加载流程:

// Launcher3/src/com/android/launcher3/Launcher.java@Override

本文标签: 中的 配置 布局