Launcher源码浅析-----Launcher布局

   前言:Launcher是Android的系统应用,在手机开机后第一个见到就是Launcher。用户通过Launcher基本上可以从整体上纵观手机中所存在的所有应用;Android源码中的Launcher分两个主要界面,一个是WorkSpace界面,就是我们俗称的桌面;另一个是AppsCustomizePagedView界面,就是我们俗称的菜单界面;Launcher可以说是Android系统中比较重要的系统应用模块,能够掌握和熟悉Launcher模块,当然是最好的,Launcher这块骨头很硬,必须要慢慢啃;个人认为,在熟悉一个系统模块之前,弄清楚它的整体布局是至关重要的,所以这篇文章主要是重点分析Launcher的相关布局,若有不当之处,还请同行们指点迷津。废话有点多了,开始吧!

   一. Launcher主入口

       Launcher就是一个系统应用, 如果想要知道Launcher中都有那些四大组件和主入口,那么通过它的AndroidManifest.xml文件代码就可以探知,如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.android.launcher">

    <original-package android:name="com.android.launcher2" />

    <!-- Launcher中自定义的权限 -->
    <permission
        android:name="com.android.launcher.permission.INSTALL_SHORTCUT"
        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
        android:protectionLevel="normal"
        android:label="@string/permlab_install_shortcut"
        android:description="@string/permdesc_install_shortcut" />
    <permission
        android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT"
        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
        android:protectionLevel="normal"
        android:label="@string/permlab_uninstall_shortcut"
        android:description="@string/permdesc_uninstall_shortcut"/>
    <permission
        android:name="com.android.launcher.permission.READ_SETTINGS"
        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
        android:protectionLevel="normal"
        android:label="@string/permlab_read_settings"
        android:description="@string/permdesc_read_settings"/>
    <permission
        android:name="com.android.launcher.permission.WRITE_SETTINGS"
        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
        android:protectionLevel="normal"
        android:label="@string/permlab_write_settings"
        android:description="@string/permdesc_write_settings"/>

    <!-- 注册系统权限 -->
    <uses-permission android:name="android.permission.CALL_PHONE" />
    <uses-permission android:name="android.permission.SET_WALLPAPER" />
    <uses-permission android:name="android.permission.SET_WALLPAPER_HINTS" />
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.BIND_APPWIDGET" />
    <uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />
    <uses-permission android:name="com.android.launcher.permission.WRITE_SETTINGS" />

    <!-- hardwareAccelerated为是否使用硬件加速,largeHeap为是否使用了大的堆内存,值在config.xml文件中定义 -->
    <application
        android:name="com.android.launcher2.LauncherApplication"
        android:label="@string/application_name"
        android:icon="@drawable/ic_launcher_home"
        android:hardwareAccelerated="@bool/config_hardwareAccelerated"
        android:largeHeap="@bool/config_largeHeap">
        <activity
            android:name="com.android.launcher2.Launcher"
            android:launchMode="singleTask"
            android:clearTaskOnLaunch="true"
            android:stateNotNeeded="true"
            android:theme="@style/Theme"
            android:windowSoftInputMode="adjustPan"
            android:screenOrientation="nosensor">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.HOME" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.MONKEY"/>
            </intent-filter>
        </activity>

        <activity
            android:name="com.android.launcher2.WallpaperChooser"
            style="@style/Theme.WallpaperPicker"
            android:label="@string/pick_wallpaper"
            android:icon="@drawable/ic_launcher_wallpaper"
            android:finishOnCloseSystemDialogs="true"
            android:process=":wallpaper_chooser">
            <intent-filter>
                <action android:name="android.intent.action.SET_WALLPAPER" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
            <meta-data android:name="android.wallpaper.preview"
                android:resource="@xml/wallpaper_picker_preview" />
        </activity>

        <activity android:name="com.android.launcher2.RocketLauncher"
            android:label="@string/dream_name"
            android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.DREAM" />
            </intent-filter>
        </activity>

        <!-- Intent received used to install shortcuts from other applications -->
        <receiver
            android:name="com.android.launcher2.InstallShortcutReceiver"
            android:permission="com.android.launcher.permission.INSTALL_SHORTCUT">
            <intent-filter>
                <action android:name="com.android.launcher.action.INSTALL_SHORTCUT" />
            </intent-filter>
        </receiver>

        <!-- Intent received used to uninstall shortcuts from other applications -->
        <receiver
            android:name="com.android.launcher2.UninstallShortcutReceiver"
            android:permission="com.android.launcher.permission.UNINSTALL_SHORTCUT">
            <intent-filter>
                <action android:name="com.android.launcher.action.UNINSTALL_SHORTCUT" />
            </intent-filter>
        </receiver>

        <!-- The settings provider contains Home's data, like the workspace favorites -->
        <provider
            android:name="com.android.launcher2.LauncherProvider"
            android:authorities="com.android.launcher2.settings"
            android:writePermission="com.android.launcher.permission.WRITE_SETTINGS"
            android:readPermission="com.android.launcher.permission.READ_SETTINGS" />

    </application>
</manifest>

        通过AndroidManifest.xm文件中的代码可以知道:

         1). com.android.launcher2.LauncherApplication类描述整个应用,该类继承Application。某种意义上来说是Launcher的主入口类;在Launcher应用创建时,最先执行的是LauncherApplication类中的onCreate()方法;LauncherApplication类中主要实现注册一些广播接收器和监听数据库改变的ContentObserver,同时对外(主要是主Activity)提供一些获取相关对象(LauncherModel、IconCache、LauncherProvider等)和屏幕密度的接口函数。

         2). com.android.launcher2.Launcher为Launcher模块的主Activity,Launcher中的灵魂类。在该主Activity的onCreate方法中执行setContentView(R.layout.launcher)加载Launcher的整个布局。

         3). com.android.launcher2.WallpaperChooser为长按桌面空白处弹出的选择壁纸相关的Activity组件。

         4).com.android.launcher2.InstallShortcutReceiver为安装快捷方式时负责接收相关广播进行操作的BroadcastReceiver组件。比如,要为自己开发的应用添加第一次启动时在桌面创建快捷键的功能,那么就需要注册com.android.launcher.permission.INSTALL_SHORTCUT权限,同时发送Intent的Action为com.android.launcher.action.INSTALL_SHORTCUT的广播。

         5). com.android.launcher2.UninstallShortcutReceiver为卸载快捷方式时负责接收相关广播进行操作的BroadcastReceiver组件。

         7). com.android.launcher2.LauncherProvider为Launcher进行数据库相关操作的ContentProvider组件。

   二. Launcher总布局文件launcher.xml浅析

       通过上文的介绍,可以知道,布局文件launcher.xml是在Launcher的onCreate方法中加载的。

       1. Launcher.xml文件代码(竖向布局)

<?xml version="1.0" encoding="utf-8"?>
<com.android.launcher2.DragLayer
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"

    android:id="@+id/drag_layer"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- Keep these behind the workspace so that they are not visible when
         we go into AllApps -->
    <!-- dock_divider为桌面分隔线,将hotseat和Workspace分隔 -->
    <include
        android:id="@+id/dock_divider"
        layout="@layout/workspace_divider"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="@dimen/button_bar_height"
        android:layout_gravity="bottom" />
    <!-- 桌面分隔线的上指示条,Workspace翻页的时候显示 -->
    <include
        android:id="@+id/paged_view_indicator"
        layout="@layout/scroll_indicator"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        android:layout_marginBottom="@dimen/button_bar_height" />

    <!-- The workspace contains 5 screens of cells -->
    <!-- Workspace即手机桌面,默认系统是包含可翻转5页 -->
    <com.android.launcher2.Workspace
        android:id="@+id/workspace"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingTop="@dimen/qsb_bar_height_inset"
        android:paddingBottom="@dimen/button_bar_height"
        launcher:defaultScreen="2"
        launcher:cellCountX="4"
        launcher:cellCountY="4"
        launcher:pageSpacing="@dimen/workspace_page_spacing"
        launcher:scrollIndicatorPaddingLeft="@dimen/workspace_divider_padding_left"
        launcher:scrollIndicatorPaddingRight="@dimen/workspace_divider_padding_right">

        <!-- Workspace总共可翻转5个页面,一个 workspace_screen定义一个页面布局-->
        <include android:id="@+id/cell1" layout="@layout/workspace_screen" />
        <include android:id="@+id/cell2" layout="@layout/workspace_screen" />
        <include android:id="@+id/cell3" layout="@layout/workspace_screen" />
        <include android:id="@+id/cell4" layout="@layout/workspace_screen" />
        <include android:id="@+id/cell5" layout="@layout/workspace_screen" />
    </com.android.launcher2.Workspace>

    <!-- qsb_bar布局包含桌面上的可搜索框 以及长按桌面上图标时显示删除和应用信息的操作框-->
    <include
        android:id="@+id/qsb_bar"
        layout="@layout/qsb_bar" />

    <!-- 点击hotseat中心图标进入的界面,该界面显示所有应用和小部件 -->
    <include layout="@layout/apps_customize_pane"
        android:id="@+id/apps_customize_pane"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="invisible" />

    <!-- hotseat为桌面分隔线下的界面, 不随Workspace翻页操作而移动 -->
    <include layout="@layout/hotseat"
        android:id="@+id/hotseat"
        android:layout_width="match_parent"
        android:layout_height="@dimen/button_bar_height_plus_padding"
        android:layout_gravity="bottom" />

    <!-- 手机刚开机,或者对launcher应用清空数据第一次进入到workspace时弹出的操作介绍界面 -->
    <include layout="@layout/workspace_cling"
        android:id="@+id/workspace_cling"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="gone" />

    <!-- 手机刚开机,或者对launcher应用清空数据,第一次打开将workspace上两个以上的图标拖到一起形成 的文件夹时弹出的操作界面-->
    <include layout="@layout/folder_cling"
        android:id="@+id/folder_cling"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="gone" />
</com.android.launcher2.DragLayer>

    2. 以下列出Launcher主要界面的截图:

         

                       图1                                                     图2                                              图3

  上面三个图比较直观的说明Launcher的主要布局:

     图1:Launcher的桌面布局(从上到下为搜索框、Workspace、分割线、hotseat)。

     图2:菜单界面(apps_customize_pane)之一的显示所有已安装的应用程序;

     图3:菜单界面(apps_customize_pane)之一的显示所有已创建的widget(小部件)

     注:菜单界面整体是一个TabHost,由两个子Tab组成;一个就是显示图2界面的子Tab,另一个就是显示图3界面的子Tab

  3. 从上到下分析Launcher.xml文件中的代码:

     1). 整个树状布局的最上层是com.android.launcher2.DragLayer,DragLayer类继承自FrameLayout,属于自定义实现的ViewGroup类型容器视图组件。DragLayer类中主要负责Launcher中相关的拖拽处理;

     2).id为dock_divider的子视图(分割线):通过< include />元素添加布局为workspace_divider(对应的布局),我们到workspace_divider.xml文件看看该子视图的真正布局,如下:

        workspace_divider.xml代码:

<?xml version="1.0" encoding="utf-8"?>
<ImageView
    xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
    android:paddingLeft="@dimen/workspace_divider_padding_left"
    android:paddingRight="@dimen/workspace_divider_padding_right"
    android:paddingTop="@dimen/workspace_divider_padding_top"
    android:paddingBottom="@dimen/workspace_divider_padding_bottom"
    android:scaleType="fitXY"
    android:src="@drawable/hotseat_track_holo" />

         由此可知id为dock_divider的子视图就是一个ImageView对象,即一条点9图的分割线;该分割线把Workspace和Hotseat分割出来;

     3). id为paged_view_indicator的子视图:该子视图对应布局为scroll_indicator,scroll_indicator.xml文件的代码如下:

<?xml version="1.0" encoding="utf-8"?>
<ImageView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
    android:visibility="gone"
    android:alpha="0"
    android:scaleType="fitXY"
    android:src="@drawable/hotseat_scrubber_holo" />
      所以,该视图也为ImageView对象,即一个点9图的蓝色指示线,当我们在桌面上滑动翻页时,该蓝色指示线会显示,用于指示翻页操作;

      4). id为workspace的子视图(Workspace界面视图):该子视图为自定义类Workspace,Workspace继承自SmoothPagedView,SmoothPagedView继承自PagedView,PagedView继承自ViewGroup;所以Workspace的终极父类也是ViewGroup;即该子视图为ViewGroup类型的自定义容器视图;在Workspace视图中又包含了5个id分别为cell1、cell2、cell3、cell4、cell5的子视图。它们对应的布局均为workspace_screen,workspace_screen.xml文件的代码如下:

<?xml version="1.0" encoding="utf-8"?>
<com.android.launcher2.CellLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
    style="@style/WorkspaceScreen"

    android:paddingLeft="@dimen/workspace_left_padding"
    android:paddingRight="@dimen/workspace_right_padding"
    android:paddingTop="@dimen/workspace_top_padding"
    android:paddingBottom="@dimen/workspace_bottom_padding"
    android:hapticFeedbackEnabled="false"

    launcher:cellWidth="@dimen/workspace_cell_width"
    launcher:cellHeight="@dimen/workspace_cell_height"
    launcher:widthGap="@dimen/workspace_width_gap"
    launcher:heightGap="@dimen/workspace_height_gap"
    launcher:maxGap="@dimen/workspace_max_gap" />
      所以,Workspace中包含的五个子视图均为自定义视图类CellLayout(CellLayout继承ViewGroup);一个 CellLayout对应Workspace中的一页(一屏),Workspace中默认情况下总共可翻转5页,所以Workspace中有5个CellLayout(cell1、cell2、cell3、cell4、cell5);Workspace的区域就是图1中位于搜索框和分割线之间的区域;

      5). id为qsb_bar的子视图:该子视图对应的布局为qsb_bar,布局文件qsb_bar.xml的代码如下:

<?xml version="1.0" encoding="utf-8"?>
<com.android.launcher2.SearchDropTargetBar
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
    style="@style/QSBBar"
    android:focusable="false"
    android:background="@drawable/search_bg_panel">

    <!-- Search buttons container -->
    <!-- 桌面上可点击的搜索框 -->
    <include android:id="@+id/qsb_search_bar"
        layout="@layout/search_bar" />

    <!-- Drag specific targets container -->
    
    <!-- 长按菜单界面快捷图标进入到桌面时显示删除和应用信息的操作框,这时候搜索框会隐藏,操作框会显示在 搜索框的位置-->
    <LinearLayout
        style="@style/SearchDropTargetBar"
        android:id="@+id/drag_target_bar"
        android:visibility="gone">

        <!-- 显示删除的布局 -->
        <FrameLayout
            style="@style/DropTargetButtonContainer"
            android:layout_weight="1">
            <!-- Delete target -->
            <com.android.launcher2.DeleteDropTarget
                style="@style/DropTargetButton"
                android:id="@+id/delete_target_text"
                android:text="@string/delete_zone_label_workspace"
                android:drawableLeft="@drawable/delete_target_selector" />
        </FrameLayout>

        <!-- 显示应用信息的布局 -->
        <FrameLayout
            style="@style/DropTargetButtonContainer"
            android:layout_weight="1">
            <!-- Info target -->
            <com.android.launcher2.InfoDropTarget
                style="@style/DropTargetButton"
                android:id="@+id/info_target_text"
                android:text="@string/info_target_label"
                android:drawableLeft="@drawable/info_target_selector" />
        </FrameLayout>
    </LinearLayout>
    
</com.android.launcher2.SearchDropTargetBar>
    该子视图的布局包含搜索框的视图布局和操作框的视图布局:

      -->搜索框对应的是id为qsb_search_bar的视图,它对应的布局文件为search_bar.xml;

      -->操作框对应的是id为drag_target_bar的视图(LinearLayout),操作框包含两部分(两个FrameLayout):一部分对应的是id为delete_target_text的布局(DeleteDropTarget),拖拽应用图标至该区域时会进入卸载应用的操作;另一部分对应的是id为info_target_text的布局(InfoDropTarget),拽应用图标至该区域时会进入显示应用程序信息的界面;如下图就是从菜单拖拽应用图标到桌面是操作框显示的示意图(屏幕上方显示操作框):

     

      6). id为apps_customize_pane的子视图(菜单界面视图):该子视图对应的布局为apps_customize_pane,apps_customize_pane文件代码如下:

<?xml version="1.0" encoding="utf-8"?>
<!-- 点击hotseat中心图标显示的菜单界面布局,该界面显示所有应用和小部件 -->
<com.android.launcher2.AppsCustomizeTabHost
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
    android:background="#FF000000">
    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <!-- The layout_width of the tab bar gets overriden to align the content
             with the text in the tabs in AppsCustomizeTabHost. -->
        <!-- Tab标签"应用程序"、"窗口小部件"和应用商店图标的视图布局 -->
        <FrameLayout
            android:id="@+id/tabs_container"
            android:layout_width="wrap_content"
            android:layout_height="@dimen/apps_customize_tab_bar_height"
            android:layout_gravity="center_horizontal">
            <com.android.launcher2.FocusOnlyTabWidget
                android:id="@android:id/tabs"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_gravity="left"
                android:background="@drawable/tab_unselected_holo"
                android:tabStripEnabled="false" />
            <include
                android:id="@+id/market_button"
                layout="@layout/market_button"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_gravity="right" />
        </FrameLayout>
        <FrameLayout
            android:id="@android:id/tabcontent"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <!-- 承载所有应用程序图标和widget的视图布局 -->
            <com.android.launcher2.AppsCustomizePagedView
                android:id="@+id/apps_customize_pane_content"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                launcher:cellCountX="@integer/apps_customize_cellCountX"
                launcher:cellCountY="@integer/apps_customize_cellCountY"
                launcher:pageLayoutWidthGap="@dimen/apps_customize_pageLayoutWidthGap"
                launcher:pageLayoutHeightGap="@dimen/apps_customize_pageLayoutHeightGap"
                launcher:pageLayoutPaddingTop="@dimen/apps_customize_pageLayoutPaddingTop"
                launcher:pageLayoutPaddingBottom="@dimen/apps_customize_pageLayoutPaddingBottom"
                launcher:pageLayoutPaddingLeft="@dimen/apps_customize_pageLayoutPaddingLeft"
                launcher:pageLayoutPaddingRight="@dimen/apps_customize_pageLayoutPaddingRight"
                launcher:widgetCellWidthGap="@dimen/apps_customize_widget_cell_width_gap"
                launcher:widgetCellHeightGap="@dimen/apps_customize_widget_cell_height_gap"
                launcher:widgetCountX="@integer/apps_customize_widget_cell_count_x"
                launcher:widgetCountY="@integer/apps_customize_widget_cell_count_y"
                launcher:clingFocusedX="@integer/apps_customize_cling_focused_x"
                launcher:clingFocusedY="@integer/apps_customize_cling_focused_y"
                launcher:maxGap="@dimen/workspace_max_gap" />
            <ImageView
                android:id="@+id/animation_buffer"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:visibility="gone" />

            <!-- 蓝色翻页指示线 -->
            <include
                android:id="@+id/paged_view_indicator"
                layout="@layout/scroll_indicator"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="bottom" />
        </FrameLayout>
    </LinearLayout>

    <!-- 第一次进入到菜单界面时弹出的操作介绍界面 -->
    <include layout="@layout/all_apps_cling"
        android:id="@+id/all_apps_cling"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="gone" />
</com.android.launcher2.AppsCustomizeTabHost>

     菜单界面视图由自定义视图类AppsCustomizeTabHost描述,该类继承TabHost,菜单界面视图中,包含了一个LinearLayout布局和一个id为all_apps_cling的视图布局(对应的布局为all_apps_cling):

     -->LinearLayout布局中又包含了两个FrameLayout(对应的id分别为tabs_container、tabcontent)。

         -->id为tabs_container的FrameLayout中包含了菜单界面中"应用程序"和“窗口小部件”这两个子Tab标签的视图布局(FocusOnlyTabWidget)和点击进入“应用商店“的图标(对应布局为market_button)。

         -->id为tabcontent的FrameLayout中包含了用来承载应用程序图标和widget的界面视图布局(AppsCustomizePagedView)和指示翻页操作的蓝色指示线(对应布局为scroll_indicator)。

     -->id为all_apps_cling的视图布局为手机恢复出厂设置(或清空Launcher数据)后第一次进入到菜单界面时弹出的操作介绍界面,如下图的界面:

          

      7). id为hotseat的子视图:该子视图对应的布局为hotseat,hotseat.xml文件的代码如下:

<?xml version="1.0" encoding="utf-8"?>
<com.android.launcher2.Hotseat
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
    android:background="@drawable/hotseat_bg_panel"
    launcher:cellCountX="5"
    launcher:cellCountY="1">
    <com.android.launcher2.CellLayout
        android:id="@+id/layout"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="center"
        android:paddingTop="@dimen/button_bar_height_top_padding"
        android:paddingBottom="@dimen/button_bar_height_bottom_padding"
        android:paddingLeft="@dimen/button_bar_width_left_padding"
        android:paddingRight="@dimen/button_bar_width_right_padding"

        launcher:cellWidth="@dimen/hotseat_cell_width"
        launcher:cellHeight="@dimen/hotseat_cell_height"
        launcher:widthGap="@dimen/hotseat_width_gap"
        launcher:heightGap="@dimen/hotseat_height_gap"
        launcher:maxGap="@dimen/workspace_max_gap" />
</com.android.launcher2.Hotseat>
       hotseat视图布局由自定义视图类Hotseat描述,该类继承自FrameLayout;hotseat视图布局包含一个CellLayout;hotseat视图布局区域就是上文图1中分割线以下的区域,如下图所示:

          

       点击中间的菜单按钮实现进入菜单界面,hotseat中的快捷图标也可以任意拖拽放置(也可以将hotseat中的快捷图标拖拽到Workspace中放置);

      8). id为workspace_cling的子视图:该视图对应的布局文件为workspace_cling.xml。视图布局为手机恢复出厂设置(或清空Launcher数据)后第一次进入到workspace时弹出的操作介绍界面,如下图所示:

                

      9). id为folder_cling的子视图:该视图对应的布局文件为folder_cling.xml;视图布局为手机恢复出厂设置(或清空Launcher数据)后第一次打开文件夹时弹出的操作介绍界面,如下图所示:

          

   


  • 2
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 15
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值