一 。如何隐藏屏幕下方的虚拟按键栏?
在源码路径framework/base/core/res/res/values/config.xml文件中,有一个标签<bool name=”config_showNavigationBar”>true<bool>,将其值设为true就可以看到虚拟按钮,设为false则会隐藏;
二。状态栏的定制
在源码的frameworks/base/packages/SystemUI路径下,这是一个完整的android工程,系统UI包括虚拟按键,状态栏的实现都在这个工程中,可以修改;
比如隐藏状态栏的电量图标,找到BatteryController.java类,可以在里面将相关的view隐藏,可参考文章Android源码开发之状态栏;
三。系统的裁剪
在源码路径device\softwinner\wing-common\preinstallapk以及googleservice下,可以自行删减无用的应用和服务,具体路径随具体情况有所变化;假如想要预装软件,也可以将apk放入preinstallapk目录下,经过编译后,在out\...\preinstallapk目录下会出现同样的文件,就可以实现软件的预装;
四。桌面背景的修改
在源码路径下frameworks\base\core\res\res下的drawable文件夹中default_wallpaper即为默认墙纸,可以在不同分辨率的文件夹中进行替换来修改;这种背景图片会成为桌面所有屏幕的共同背景,比如桌面有5个屏幕,那么5个屏幕所显示出的所有画面拼接起来才会形成完整的墙纸图片,而且可以通过设置墙纸来进行修改;
此外,还可以在系统应用Launcher中,通过修改launcher.xml布局文件的背景来实现一个不可修改的背景,比如我之前所实现的桌面,需要一个类似窗框的背景,即在桌面四周有一周的黑边,见下图:
那么就可以采用这种方法。
五。Launch定制
Android4.2中的launcher。xml源码如下:
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:launcher="http://schemas.android.com/apk/res/com.test.launcher"
android:id="@+id/launcher"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.test.launcher2.DragLayer
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:launcher="http://schemas.android.com/apk/res/com.test.launcher"
android:id="@+id/drag_layer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<!-- Keep these behind the workspace so that they are not visible when
we go into AllApps -->
<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_plus_padding"
android:layout_gravity="bottom|center_horizontal" />
<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_plus_padding" />
<!-- The workspace contains 5 screens of cells -->
<com.test.launcher2.Workspace
android:id="@+id/workspace"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/workspace_left_padding"
android:paddingRight="@dimen/workspace_right_padding"
android:paddingTop="@dimen/workspace_top_padding"
android:paddingBottom="@dimen/workspace_bottom_padding"
launcher:defaultScreen="2"
launcher:cellCountX="@integer/cell_count_x"
launcher:cellCountY="@integer/cell_count_y"
launcher:pageSpacing="@dimen/workspace_page_spacing"
launcher:scrollIndicatorPaddingLeft="@dimen/workspace_divider_padding_left"
launcher:scrollIndicatorPaddingRight="@dimen/workspace_divider_padding_right">
<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.test.launcher2.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" />
<include
android:id="@+id/qsb_bar"
layout="@layout/qsb_bar" />
<!-- The Workspace cling must appear under the AppsCustomizePagedView below to ensure
that it is still visible during the transition to AllApps and doesn't overlay on
top of that view. -->
<include layout="@layout/workspace_cling"
android:id="@+id/workspace_cling"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />
<include layout="@layout/folder_cling"
android:id="@+id/folder_cling"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />
<com.test.launcher2.DrawableStateProxyView
android:id="@+id/voice_button_proxy"
android:layout_width="80dp"
android:layout_height="@dimen/qsb_bar_height"
android:layout_marginRight="@dimen/qsb_voice_proxy_padding_right"
android:layout_gravity="top|right"
android:clickable="true"
android:onClick="onClickVoiceButton"
android:importantForAccessibility="no"
launcher:sourceViewId="@+id/voice_button" />
<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" />
</com.test.launcher2.DragLayer>
</FrameLayout>
1. view介绍
可以通过给FrameLayout设置background属性来设置背景;
DragLayer和WorkSpace都是FrameLayout的直接或间接子类;
dock_divider就是主屏幕workspace与底座hotseat之间的分隔线;
paged_view_indicator就是屏幕序号指示,和dock_divider重合;
workspace就是主屏幕view,桌面上的快捷方式,文件夹,widget等都是放在它里面,可以看到它里面包裹了5个workspace_screen,每一个都由CellLayout组成,代码桌面的5个屏,你可以通过增删来修改屏幕数量;
hotseat就是底座;
qsb_bar就是workspace上方的谷歌搜索栏以及长按后会出现的删除按钮;
workspace_cling和folder_cling是第一次启动桌面时,会出现的提示;
apps_customize_pane就是所有应用列表界面,点击home键之后它才会出现遮挡住workspace;
2. workspace
defaultScreen指定默认屏幕为第几个;
CellCountX为横向格栏个数,CellCountY为纵向格栏个数,这2个属性将真个workspace主屏幕分为若干个小方格,每一个快捷方式,文件夹,widget都通过指定位置放置在特定的小方格中;
workspace中实际容纳图标的是cellLayout,而hotseat中同样是由cellLayout作为最终盛放容器,所以它们在处理逻辑上是一致的,通过是否hotseat来实现特殊化;
3.hotseat
hotseat背景可以通过设置background属性来实现,其高度也可以任意控制;
Android4.2的Launcher的hotseat.xml源码如下:
<com.test.launcher2.Hotseat
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:launcher="http://schemas.android.com/apk/res/com.test.launcher"
launcher:cellCountX="@integer/hotseat_cell_count"
launcher:cellCountY="1">
<com.test.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/hotseat_width_gap" />
</com.test.launcher2.Hotseat>
(1)cellWidth和cellHeight分别控制图标的宽度和高度;
如果想要修改hotseat中图标的大小,光靠这2个属性恐怕还不行;在CellLayout.java中有个变量mHotseatScale,它代表hotseat内图标的缩放量,只有这3个量一起,才能达到修改hotseat内图标大小的最佳效果;
(2)无论是workspace还是hotseat内的一般图标的显示,都使用的是BubbleTextView控件,它继承于TextView;
通过将图片作为背景显示在文字上方的方式(TextView的setCompoundDrawables系列方法),来实现我们在桌面上看到的效果;
而hotseat中的图标是没有文字显示的,它是通过在CellLayout.java中的addViewToCellLayout()方法中设置字体颜色为透明来实现,但这种实现方法实际上文字仍然占用空间,只是我们看不到而已,同样可以通过设置文字大小为0来实现效果;
假如你要将hotseat内的图标放大,会发现图片可能显示不完整,那是因为看不见的透明文字也随之被放大并占用了空间,这时可以通过修改文字和图片的位置关系,设置文字大小,设置padding值来进行调整;
(3)all_apps_button也就是所有应用列表按钮,是在HotSeat.java中动态加载的,它也是一个BubbleTextView,它的位置可以通过config.xml文件中的hotseat_all_apps_index属性来设置,默认都是居于中间;
在Launcher.java中有一个onClickAllAppsButton()方法,这个按钮最终触发的就是这个方法;
(4)hotseat中的默认图标设置是在xml文件夹里的default_workspace.xml里面,一个典型的andrid4.2源码实例如下:
<favorites xmlns:launcher="http://schemas.android.com/apk/res/com.test.launcher">
<!-- Far-left screen [0] -->
<!-- Left screen [1] -->
<appwidget
launcher:packageName="com.android.settings"
launcher:className="com.android.settings.widget.SettingsAppWidgetProvider"
launcher:screen="1"
launcher:x="2"
launcher:y="1"
launcher:spanX="4"
launcher:spanY="1" />
<!-- Middle screen [2] -->
<!-- Right screen [3] -->
<!-- Far-right screen [4] -->
<!-- Hotseat (We use the screen as the position of the item in the hotseat) -->
<favorite
launcher:packageName="com.google.android.music"
launcher:className="com.android.music.activitymanagement.TopLevelActivity"
launcher:container="-101"
launcher:screen="1"
launcher:x="1"
launcher:y="0" />
<favorite
launcher:packageName="com.android.gallery3d"
launcher:className="com.android.gallery3d.app.Gallery"
launcher:container="-101"
launcher:screen="2"
launcher:x="2"
launcher:y="0" />
<favorite
launcher:packageName="com.android.gallery3d"
launcher:className="com.android.camera.CameraLauncher"
launcher:container="-101"
launcher:screen="4"
launcher:x="4"
launcher:y="0" />
<favorite
launcher:packageName="com.android.settings"
launcher:className="com.android.settings.Settings"
launcher:container="-101"
launcher:screen="5"
launcher:x="5"
launcher:y="0" />
<favorite
launcher:packageName="com.android.browser"
launcher:className="com.android.browser.BrowserActivity"
launcher:container="-101"
launcher:screen="6"
launcher:x="6"
launcher:y="0" />
<!-- Hotseat (We use the screen as the position of the item in the hotseat) -->
<folder
launcher:title="@string/naming_is_Google"
launcher:container="-101"
launcher:screen="0"
launcher:x="0"
launcher:y="0" >
<favorite
launcher:className="com.google.android.gm.ConversationListActivityGmail"
launcher:packageName="com.google.android.gm" />
<favorite
launcher:className="com.google.android.apps.plus.phone.HomeActivity"
launcher:packageName="com.google.android.apps.plus" />
<favorite
launcher:className="com.google.android.maps.MapsActivity"
launcher:packageName="com.google.android.apps.maps" />
<favorite
launcher:className="com.android.music.activitymanagement.TopLevelActivity"
launcher:packageName="com.google.android.music" />
<favorite
launcher:className="com.google.android.youtube.videos.EntryPoint"
launcher:packageName="com.google.android.videos" />
<favorite
launcher:className="com.google.apps.dots.android.app.activity.CurrentsStartActivity"
launcher:packageName="com.google.android.apps.magazines" />
<favorite
launcher:className="com.google.android.apps.books.app.BooksActivity"
launcher:packageName="com.google.android.apps.books" />
<favorite
launcher:className="com.google.android.youtube.app.honeycomb.Shell$HomeActivity"
launcher:packageName="com.google.android.youtube" />
<favorite
launcher:className="com.google.android.talk.SigningInActivity"
launcher:packageName="com.google.android.talk" />
<favorite
launcher:className="com.android.calendar.AllInOneActivity"
launcher:packageName="com.google.android.calendar" />
<favorite
launcher:className="com.google.android.apps.chrome.Main"
launcher:packageName="com.android.chrome" />
<favorite
launcher:packageName="com.android.vending"
launcher:className="com.android.vending.AssetBrowserActivity"/>
</folder>
</favorites>
container为-101指的是hotseat,由此可以看到默认的hotseat布局是怎么样的;
有一篇关于这方面的博客写的非常好,Android Launcher分析和修改,强烈推荐。
六。关于Widget
widget就是桌面小部件;
在本次开发中,有一个桌面模拟时钟的需求,我根据AnalogClock的源码自己实现了一个模拟时钟,结果发现怎么样也没办法显示出来,后来在论坛上通过一位大仙的指导,才醍醐灌顶:widget里面所能使用的view是非常有限的,具体支持的view可参看sdk,明显它是不能放置自定义控件的;
不过后来我发现系统提供的AnalogClock模拟时钟其实是支持定制的,我们可以指定自己的表盘,指针等,而且它是被widget支持的,所以最后用这个方法很简单就实现了需求;
但是后来也在网上发现一篇文章,表示在源码环境下我们是有办法让任意的view都可以被widget所支持的,具体可参考这篇文章:Android之widget添加自定义控件介绍