Launcher的界面的rootview是DragLayer,它是一个FrameLayout,在它上面workspace(应该说是celllayout)占了绝大部分的空间,celllayout的参数文件是workspace_screen.xml。workspace既是一个DropTarget又是一个DragSource,可以从AllAppGridView中拖出应用程序放在它上面,也可以把它里面的item拖走删除或者拖到bottomabr里面去。

2.Drop& Drag模型:

DragSource:可以拖动的对象来源的容器,在launcher中主要有AllAppGridView,workspace等。

void

onDropCompleted(View target, boolean success,int x,int y);

DropTarget:可以放置被拖动的对象的容器。在launcher中有folder,workspace,bottombar等,一个View既可以是Dragsource也可以是DropTarget。主要包含以下几个接口:

boolean acceptDrop(DragSource source, int x, int y, int xOffset,

int yOffset, Object dragInfo);

acceptDrop函数用来判断dropTarget是否可以接受item放置在自己里面。

void

onDragEnter(DragSource source, int x, int y, int xOffset, int

yOffset, Object dragInfo);

onDragEnter是item被拖动进入到一个dropTarget的时候的回调。

void

onDragOver(DragSource source, int x, int y, int xOffset, int

yOffset, Object dragInfo);

onDragOver是item在上一次位置和这一次位置所处的dropTarget相同的时候的回调。

void

onDragExit(DragSource source, int x, int y, int xOffset, int

yOffset, Object dragInfo);

onDragExit是item被拖出dropTarget时的回调。

boolean onDrop(DragSource source, int x, int y, int xOffset, int

yOffset, Object dragInfo);

onDrop是item被放置到dropTarget时的回调。

函数的调用模式为:

DropTarget dropTarget = findDropTarget((int) x, (int) y,

coordinates);

if (dropTarget

!= null) {

if (mLastDropTarget ==

dropTarget) {

dropTarget.onDragOver(mDragSource,

coordinates[0], coordinates[1],

(int) mTouchOffsetX,

(int) mTouchOffsetY, mDragInfo);

} else {

if (mLastDropTarget != null)

{

mLastDropTarget.onDragExit(mDragSource,

coordinates[0], coordinates[1],

(int) mTouchOffsetX,

(int) mTouchOffsetY, mDragInfo);

}

dropTarget.onDragEnter(mDragSource,

coordinates[0], coordinates[1],

(int) mTouchOffsetX,

(int) mTouchOffsetY, mDragInfo);

}

} else {//如果这一次为 null

,上一次不为 null

,那么把上一次坐标位置的 cell 去掉

if (mLastDropTarget != null)

{

mLastDropTarget.onDragExit(mDragSource,

coordinates[0], coordinates[1],

(int) mTouchOffsetX,

(int) mTouchOffsetY, mDragInfo);

}

}

//记录上次的droptarget

mLastDropTarget =

dropTarget;

3.Touch event总结:

由于launcher的事件比较多比较复杂,所以在事件处理的时候一般采用rootview先用onInterceptTouchEvent(MotionEvent)拦截所有的touch事件,经过判断后分发给childview。

判断的规则如下:

a.down事件首先会传递到onInterceptTouchEvent()方法

b.如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return

false,那么后续的move,

up等事件将继续会先传递给该ViewGroup,之后才和down事件一样传递给最终的目标view的onTouchEvent()处理。

c.如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return

true,那么后续的move,

up等事件将不再传递给onInterceptTouchEvent(),而是和down事件一样传递给该ViewGroup的onTouchEvent()处理,注意,目标view将接收不到任何事件。

d.如果最终需要处理事件的view的onTouchEvent()返回了false,那么该事件将被传递至其上一层次的view的onTouchEvent()处理。

e.如果最终需要处理事件的view 的onTouchEvent()返回了true,那么后续事件将可以继续传递给该view的onTouchEvent()处理。

三、几种问题的解决方式

1.将所有的应用都排列在桌面上

将所有的应用都排列在桌面是通过首先创建一个三维的boolean型全局数组来记录item的排列情况,第一维是屏数,第二维是纵向上的排列情况,第三维是横向的排列情况,如果那个位置被item所占用就标记为1,否则标记为0.在启动时把全局数组初始化为0,然后在添加的时候把相应的位置置1.凡是涉及到workspace上item的变化,比如移动、添加、删除操作时都需要维护数组,保持数组的正确性,因为在安装新程序时依据数组的状态去判断把item加到什么位置。

2.动态增加屏幕

动态增加屏幕是通过worksapce

.addchild(view)的方式实现。基本思路是:首先预先规定所允许的最大的屏幕数,然后在需要增加屏幕而且当前屏幕数没有超过最大屏幕数的时候通过(CellLayout)mInflater.inflate(R.layout.workspace_screen,null)创建一个celllayout实例出来,然后通过addchild把它加入进去。在屏幕上的item被删除时通过从最后一屏起判断屏幕上是否有item,如果有的话保留,没有的话则删除最后一屏,以此类推。

3.预制桌面

a.添加普通的应用程序快捷方式:

在../res/xml下的default_workspace.xml文件中加入默认要放置的普通的应用程序。加入的格式为:

launcher:packageName="...

" //应用的packageName

launcher:className="...

" //应用启动时的第一个activity

launcher:screen="..." //放置在第几屏(放在workspace的时候需要,从0开始,0为第一屏,1为第二屏,以此类推...)

launcher:x="..." //放置x方向的位置(在列中的位置)

launcher:y="..."

/> //放置y方向的位置(在行中的位置)

packageName和className可以通过点击程序,然后在打印出的log中找到comp={...},例如如下信息:

comp={com.estrongs.android.taskmanager/com.estrongs.android.taskmanager.TaskManager}。其中com.estrongs.android.taskmanager为packageName,

com.estrongs.android.taskmanager.TaskManager为className。

workspace的布局如下:

(0,0)

(1,0)

(2,0)

(3,0)

(4,0)

(0,1)

(1,1)

(2,1)

(3,1)

(4,1)

(0,2)

(1,2)

(2,2)

(3,2)

(4,2)

b.添加widget:

在../package/apps/VLauncher/res/xml下的default_workspace.xml文件中加入默认要放置的普通的应用程序。加入的格式为:

launcher:packageName="..." //widget的packageName

launcher:className="

..." //实现 widget的 receiver 类的名称.

launcher:container="..."//放置的位置(只能为desktop)

launcher:screen="..." //放置在第几屏上

launcher:x="..."//放置的x位置

launcher:y="..." //放置的y位置

launcher:spanx="..."//在x方向上所占格数

launcher:spany="..."/> //在y方向上所占格数

例如,要在第3屏的第一行第二列放置开始放置一个x方向上占两个单位格,y方向上占两个单位格的时钟,可以加入以下代码:

launcher:packageName="com.android.alarmclock" launcher:className="com.android.alarmclock.AnalogAppWidgetProvider"

launcher:container="desktop"

launcher:screen="2"

launcher:x="1"

launcher:y="0"

launcher:spanx="2"

launcher:spany="2"/>

4.改变主界面的排列方式

要修改桌面的排列方式,如下,先根据横竖屏设置修改workspace_screen.xml里shortAxisCells和longAxisCells的参数,然后在Launcher.java中修改NUMBER_CELLS_X和NUMBER_CELLS_Y的值,在2.3版本中刚开始往数据库中添加item的时候会去判断,如果不修改NUMBER_CELLS_X和NUMBER_CELLS_Y的话会导致一部分的item显示不出来,导致预制apk的失败。

5.增加worksapce上的屏数

要增加屏数,首先在根据横竖屏在launcher.xml中的,然后在Launcher.java中修改SCREEN_COUNT的值即可。

四、xml文件

1.workspace_screen.xml

launcher:cellWidth="95dip"

cell(即item)的宽

launcher:cellHeight="93dip"

cell(即item)的宽

launcher:longAxisStartPadding="25dip"

较长(屏幕的宽和高中较大的那一方向,根据横竖屏方向有所不同)方向上距离起点的像素数

launcher:longAxisEndPadding="55dip"

较长(屏幕的宽和高中较大的那一方向,根据横竖屏方向有所不同)方向上距离终点的像素数

launcher:shortAxisStartPadding="20dip"

较短(屏幕的宽和高中较大的那一方向,根据横竖屏方向有所不同)方向上距离起点的像素数

launcher:shortAxisEndPadding="120dip"

较短(屏幕的宽和高中较大的那一方向,根据横竖屏方向有所不同)方向上距离起点的像素数

launcher:shortAxisCells="3"

较短的方向上可以容纳的cell的数量

launcher:longAxisCells="5"

较长的方向上可以容纳的cell的数量

shortAxisCells和longAxisCells决定一个workspace(即CellLayout)上可以容纳的item的个数为shortAxisCells*longAxisCells.

2. application_boxed.xml

所有应用程序和系统文件夹中item的定义。

3.application.xml

Workspace的item的layout定义。

解决壁纸显示不完整的问题:

问题在于Launcher.java里面的setWallpaperDimension方法,它检查横竖屏时将宽和高搞反了,所以造成设置壁纸尺寸时

wpm.suggestDesiredDimensions总是显示不正常。

壁纸分为动态和静态两种:

如果只需要修改默认静态壁纸,替换frameworks/base/core/res/res/drawable/default_wallpaper.jpg即可,或者在源码中修改对应default_wallpaper地址.

修改动态壁纸:在frameworks/base/core/res/res/values目录找到Config.xml文件,最后一行有定义:

null 将其修改为对应的live wallpaper的启动component即可。

静态的图片壁纸和live

wallpaper是两个系统,加载的时候是完全两套机制,静态图片通过launcher里面的一个xml文件配置来管理系统默认静态壁纸,live

wallpaper则是通过intent机制向系统搜寻所有匹配Activity,所以,这里的默认值为null,而不是那个系统默认静态壁纸的地址,系统是读config.xml文件的设置,若为null才继续查找静态壁纸配置内容.

android 壁纸改变回调,android_launcher的源码详细分析和壁纸修改相关推荐

  1. android_launcher的源码详细分析和壁纸修改 .

    一.主要文件和类 1.Launcher.java:launcher中主要的activity. 2.DragLayer.java:launcher layout的rootview.DragLayer实际 ...

  2. android_launcher的源码详细分析

    转载请注明出处:http://blog.csdn.net/fzh0803/archive/2011/03/26/6279995.aspx 去年做了launcher相关的工作,看了很长时间.很多人都在修 ...

  3. LinkedHashMap 源码详细分析(JDK1.8)

    1. 概述 LinkedHashMap 继承自 HashMap,在 HashMap 基础上,通过维护一条双向链表,解决了 HashMap 不能随时保持遍历顺序和插入顺序一致的问题.除此之外,Linke ...

  4. linkedhashmap 顺序_LinkedHashMap 源码详细分析(JDK1.8)

    1. 概述 LinkedHashMap 继承自 HashMap,在 HashMap 基础上,通过维护一条双向链表,解决了 HashMap 不能随时保持遍历顺序和插入顺序一致的问题.除此之外,Linke ...

  5. FBReader源码详细分析 序言

    2019独角兽企业重金招聘Python工程师标准>>> FBReader源码详细分析 -- 序言 有关FBReader源码的分析,网络上已经有一位叫做"谋哥"的大 ...

  6. android view 源码分析,Android ViewPager源码详细分析

    1.问题 由于Android Framework源码很庞大,所以读源码必须带着问题来读!没有问题,创造问题再来读!否则很容易迷失在无数的方法与属性之中,最后无功而返. 那么,关于ViewPager有什 ...

  7. HashMap 源码详细分析(JDK1.8)

    1. 概述 本篇文章我们来聊聊大家日常开发中常用的一个集合类 - HashMap.HashMap 最早出现在 JDK 1.2中,底层基于散列算法实现.HashMap 允许 null 键和 null 值 ...

  8. vboot源码详细分析-1

    最近一直在研究bootloader之vboot,vboot短小精悍,如果只是用来进行系统的引导,而不要提供其他复杂的功能时候,我认为这是绝佳的上选.这里以MINI2440开发板配套的源码进行分析.这个 ...

  9. Android的开机流程及对应源码位置分析

    点击打开链接 1.系统引导bootloader 1)源码:bootable/bootloader/* 2)说明:加电后,CPU将先执行bootloader程序,此处有三种选择 a)开机按Camera+ ...

  10. DownloadProvider 源码详细分析

    DownloadProvider 简介 DownloadProvider 是Android提供的DownloadManager的增强版,亮点是支持断点下载,提供了"开始下载",&q ...

最新文章

  1. python代码通过日期获得星期信息(根据日期获取星期day of the week)
  2. 数据库服务器 之 在Linux下使用perl通过unixODBC连接SQLServer2000
  3. 去掉easyui datagrid内部虚线的方式。
  4. uefi装原版win8.1怎么装|uefi gpt启动模式安装win8原版系统步骤
  5. python基础===利用unittest进行测试用例执行的几种方式
  6. Python学习笔记:模块与包
  7. css_selector定位总结
  8. 关于Xcode7中添加不了libresolv.dylib等类似库的问题
  9. java中利用正则表达式获取a标签
  10. python基础:集合(set)
  11. Word2013实战技巧
  12. 基础网络连接及拓扑图
  13. 4ME1,4W1H,5W2H,6W2H,6W3H,6S、8D等……含义?
  14. django之admin调整页面展示
  15. 二元灰狼优化(BGWO)应用于特征选择任务(Matlab代码实现)
  16. 我的世界服务器核心文件,minecraft1.9服务端核心Paper
  17. 北航计算机学院直博多少年,北航硕博连读需要几年
  18. 单片机原理及应用 实验一 计数显示器
  19. DNS服务解析与原理笔记
  20. 修改Chromium源码实现HEVC/H.265 4K视频播放

热门文章

  1. PDF破解FileOpenPlugin加密的方法
  2. 第三天---网络系统硬件
  3. 海南省主要城市商品住宅价格分析
  4. 怎么删除远程桌面连接IP记录 删除连接信息
  5. 前端路由UmiJs快速上手
  6. zabbix 3.2 php,zabbix3.2.3安装教程
  7. 【黑苹果 Hackintosh】Delll成就5468(Vostro 5468)黑苹果
  8. 修改app的名字和图标
  9. IntelliJ IDEA 2017 汉化包及教程
  10. Python移植MATLAB的巴特沃斯滤波器,椭圆滤波器