说说Android桌面(Launcher应用)背后的故事(一)——揭开她神秘的面纱

时间:2022-11-24 17:47:45

 博客搬家啦——为了更好地经营博客,本人已经将博客迁移至www.ijavaboy.com。这里已经不再更新,给您带来的不便,深感抱歉!这篇文章的新地址:点击我说说Android桌面(Launcher应用)背后的故事(一)——揭开她神秘的面纱


         最近由于项目需要自己定制一套管理系统,遂想到了Android的启动器,下来了源码,一编译到处是错,查了查原因,原来是引用了自家的成员,他们家开发的就是方便,想直接用就直接用。于是下载了个包,终于错误少了一大半。但是还有一些错误,主要是引用了一些不存在的资源。于是改了改,基本可以运行了。

但是,问题来了,一眼望去,红色叉叉是不见了,但是革命依然不容乐观,一个人我认识,但是一下子成千上百个人出现在我的面前,我就不是一点点晕了,而是晕的不行了。然而,军令如山,纵然晕,也得硬着头皮将革命进行下去,因为有一点是肯定的,革命必须胜利,不容失败!

        接下来的一系列文章,就记录下我的革命之旅!本来打算在原有launcher的基础上修改的,但是后来发现,功能不需要它那么复杂,改动的地方也挺多,所以,就一边分析源码一边自己重新写了,说是重新写,其实就是抄,但是抄有抄的好处,老师布置作业的时候,作业没有作对的时候,老师总会说,这个字母抄三百遍,那个单词抄一百遍...可见抄的多了,也就记住了。但是前提是用心抄,不能小和尚念经,有口无心。这里,当然不能抄个百遍,抄个一遍就消费了上亿个脑细胞。自己写的话,我们能更好地思考,我要实现哪些功能,每个功能如何实现,系统Launcher是如何实现的,这样带着问题去分析,就很容易分门别类,理清思路,不至于在浩瀚的代码中迷失方向。

        言归正传,要想自己写个一模一样的Launcher来,我们就得先对着模拟器或者Android系统的机子,好好对每次第一个启动起来的这个看似简单却深藏不露的启动器。通过一番折腾,大致可以将Launcher实现的功能分为如下几个:

     1、在空的位置长按,具备添加应用、快捷方式、文件夹和小部件的功能

     2、左右可以滑动的屏幕

     3、可以更换壁纸

     4、长按桌面上面某个item(上面说的四个可以添加到桌面的东东),就可以任意拖动了,同时下面的SldingDrawer位置会变成一个垃圾箱,你将拖拽的item放到垃圾箱的位置其颜色变红的时候,就意味着你一放手,该item就被删除了

     5、桌面下方是个SlidingDrawer,你一点就弹上来,在里面就是所有的应用,长按可以将其拖到桌面。

 

有了这样几个功能分类,我们的任务也就非常明了了。我们就来分析并思考怎么样才能实现每个功能,最后融合为你现在所看到的效果。

我们首先看第一个问题。

简单的思考了下,觉得应该很简单,就是监听下界面的长按事件,在该事件中,弹出一个应用列表就OK了,如果这个弹出的应用列表还可以调用系统自带的,那就更省事了。

第二个问题:

滑动的屏幕,一开始还不知道怎么实现,晚上下班的时候,一个人闷闷不乐地上了公交车,站到了窗口的位置,一双黯然的眼神充满了犹豫,可是脑子里始终是这个问题。当公交车开动的时候,当窗外的一切在我的眼前缓缓向后退去的时候,我如梦初醒,失声惊叫,原来如此!幸好声音不大,否则又要出丑一次。原来手机屏幕就相当于公交车的窗口,背后是一个大风景,只不过当我们拿着手机的时候,这个窗口是静止的,但是当我们滑动的时候,风景是随着移动的。至于,这个是怎么移动的等细节问题,后面再去慢慢分析。

第三个问题:

关于更换壁纸,由于之前做过一个,所以,不用想太多,直接调用调用系统壁纸选择应用,再实现一个BroadcastReciever,监听下壁纸的改变,获得一个Bitmap类型就行了。

但是这里关键是获得Bitmap后如何将其显示出来,并随着屏幕的滑动,壁纸也要相应地移动,这里壁纸就相当于上面讲的风景,目前想到的是直接将其设置为背景,但是觉得在多个屏幕之间,不可行。

第四个问题:

拖动本身并不难,但是要在多个屏幕之间拖动就比较难办了。这个没有具体的思路,只能在实现第二个问题后,再融合多屏幕和拖拽的功能了。

第五个问题:

这个很简单,SlidingDrawer的content为一个GridView,GridView的每个item就是一个应用,关键是长按某个item就将其拖动到桌面,这个暂时也么有思路,待后面走到这一步再思考吧。

 

到此,要实现的功能已经各个功能大致的思路就有了。但是,当要下手时,又发现光有这些还是毫无头绪,没办法,还是要先来打第一仗,做到了解“敌人”的目的。所以,对Launcher的源码大致看了下,主要看其每个类的用途,找准其设计思想。这里不用纠结于某个类的某个具体的方法的具体功能,只需要知道每个类是干什么的就可以了,然后分个主次关系,看看哪些是关键,哪些是次要的,哪些是附属品...

经过第一战役,获得如下成果:

一、桌面的每种类型的item进行了类的封装,主要层次关系如下图:

——ItemInfo

         ——ApplicationInfo

         ——FolderInfo

                     ——LiveFolderInfo

                    ——UserFolderInfo

        ——Widget

 

二、整个布局层次如下图:

——DragLayer

            ——Workspace

                           ——CellLayout

                                       ——CellInfo(Application,Shortcut,Folder,Widget)

                          ——CellLayout

                          ——CellLayout

-----------------------------------------

三、关键的几个重要的类:CellLayout,Workspace,Launcher,DragLayer,把握这几个基本就清楚了桌面的布局。其中最外层是DragLayer,控制桌面上item的拖动,DragLayer中是一个Workspace,Workspace就是整个桌面,由几个CellLayout横铺组成,主要控制多屏幕的滑动,壁纸的绘制;CellLayout是一个自定义布局控件,其功能类似一个GridView,由m*n个单元格(Cell)组成,其主要负责桌面长按事件的处理,获得长按的区域信息,主要需要判断当前区域是空的还是已经被占用了,同时,控制item的拖动。CellLayout中放的就是上面几种类型的item了。item的拖动功能,是由DragLayer,Workspace,CellLayout协同完成的。

 

好了,至此,基本应用可以动手了。先不关注其他类的具体用途,先搞定所有的布局!

下一篇将具体解决第一个功能,同时深入CellLayout的背后,一探CellLayout的究竟。。。