android launcher3,Android Launcher3 基本功能分析
Android Launcher3 基本功能分析
1, 界面的布局, 从上往下分别为:DeleteDropTarget(应用卸载区域,它是一个DropTarget)
Workspace(页面容器,一个页面是一个CellLayout)
PageIndicator(指示器,指示workspace当前位于第几个页面)
Hotseat(底部图标区域)
2,Launcher 桌面图标的加载:
LauncherApplication:onCreate()创建 IconCache 和 LauncherModel, 并为 LauncherModel 设置广播过滤条件, 如应用安装广播, 配置切换广播等 ;
Launcher:onCreate()创建 DragController,LauncherAppWidgetHost, 用 setupViews()初始化各个 view ;
LauncherModel:startLoader() 开启 LoaderTask 线程, 用于加载桌面图标 ;
LauncherModel:loadAndBindWorkspace()分为 loadWorkspace 和 bindWorkspace 两个过程, 如果是刚刷完机或恢复出厂设置, loadWorkspace 会解析相应的 xml 文件, 从中读取 workspace 和 hotseat 的图标配置, 插入到新创建的 launcher.db 数据库中, 并形成相应的数据结构: sBgWorkspaceItems,sBgAppWidgets,sBgFolders. 如果已经存在了 launcher.db 文件, 则直接查询 launcher.db, 加载相应的数据结构. 而 bindWorkspace, 顾名思义, 是进行桌面图标的绑定, 也就是根据 loadWorkspace 生成的数据结构来创建并显示图标的过程, 它会依次调用 Launcher 的 bindItems(),bindFolders,bindAppWidgets, 先显示当前页面, 再显示其他页面.
3, 数据结构 (data) 和视图 (view) 的对应关系:
桌面应用: shortcutInfo 对应 BubbleTextView
所有应用: AppInfo 对应 BubbleTextView
桌面小部件: LauncherAppWidgetInfo 对应 LauncherAppWidgetHostView
文件夹: FolderInfo 对应 FoldeIcon
4, 图标的拖拽:
谈拖拽, 首先要谈 2 个概念, DragSource 和 DropTarget.DragSource 是拖拽源所在的容器, DropTarget 则为拖拽目的地所处的容器.
DragSource:Workspace,Folder 和 AppcustomizedPagedView. 注意, Hotseat 逻辑上应当也属于 DragSource, 只是我们的代码中把它归并 Workspace 中去处理了.
DropTarget:Workspace,Folder,DeleteDropTarget.Workspace 中图标的拖拽, 是从 Launcher 的 onLongClick 开始的, Folder 则从它自己的 onLongClick 开始.
以 Workspace 中的图标拖拽为例, 流程如下:Launcher:onLongClick->
Workspace:startDrag->Workspace:createDragOutline->
Workspace:beginDragShared->
DragController:startDrag->DragController:handleMoveEvent
上面是图标长按, 触发的一系列函数调用, 如果此时, 再滑动呢, 根据下面的函数
DragController 的 onTouchEvent 中caseMotionEvent.ACTION_MOVE:
handleMoveEvent(dragLayerX,dragLayerY);
break;
可知, 滑动时会不断触发 handleMoveEvent, 这样就能看到图标跟着手移动了.
那么跟手移动的虚图标是在哪里绘制的呢, 前面说到了 DragSource 和 DropTarget, 在你拖动图标到放手的过程中, 会依次调用 DragController.DragListener 的 onDragStart,
DropTarget 的 onDragEnter,onDragOver,onDragExit,onDrop,
DragSource 的 onDropCompleted,
最后会调用 DragController.DragListener 的 onDragEnd.
应用虚图标的绘制是放在 Workspace 的 onDragOver 中:if(!nearestDropOccupied&&!isWidgetOverView&&(mAuroraSwapTag||!mFromDesktopTag)){
mDragTargetLayout.visualizeDropLocation(child,mDragOutline,
(int)mDragViewVisualCenter[0],(int)mDragViewVisualCenter[1],
mTargetCell[0],mTargetCell[1],item.spanX,item.spanY,false,
d.dragView.getDragVisualizeOffset(),d.dragView.getDragRegion());
}
滑动时, Workspace 的 onDragOver 会跟着手不断被执行, 根据计算出来的最近的位置, 来放置 mDragOutline. 被拖拽图标的隐藏和显示分别在 startDrag 和 onDropCompleted 中处理的. 比较特殊的是, 当滑动到 Workspace 的边界的时候, 边界位置会显示条状的蓝色竖线, 然后决定页面是否跳转, 代码如下, 这也是在 DragController 的 handleMoveEvent 中if(x
if(mScrollState==SCROLL_OUTSIDE_ZONE){
mScrollState=SCROLL_WAITING_IN_ZONE;
if(mDragScroller.onEnterScrollArea(x,y,SCROLL_LEFT)){
mLauncher.getDragLayer().onEnterScrollArea(SCROLL_LEFT);
mScrollRunnable.setDirection(SCROLL_LEFT);
mHandler.postDelayed(mScrollRunnable,delay);
}
}
}elseif(x>mScrollView.getWidth()-mScrollZone&&y
if(mScrollState==SCROLL_OUTSIDE_ZONE){
mScrollState=SCROLL_WAITING_IN_ZONE;
if(mDragScroller.onEnterScrollArea(x,y,SCROLL_RIGHT)){
mLauncher.getDragLayer().onEnterScrollArea(SCROLL_RIGHT);
mScrollRunnable.setDirection(SCROLL_RIGHT);
mHandler.postDelayed(mScrollRunnable,delay);
}
}
}else{
clearScrollRunnable();
}
}
如果不是长按事件, 只是滑动页面, 则 DragLayer 的 OnInterceptTouchEvent 会返回 false, 把事件传递给 Workspace 去处理.
5, 图标推挤:
在 Workspace.java 的 onDragOver 方法里边处理的if(!nearestDropOccupied){// 有空位, 不需要推挤图标, 直接放置
mDragTargetLayout.visualizeDropLocation(child,mDragOutline,
(int)mDragViewVisualCenter[0],(int)mDragViewVisualCenter[1],
mTargetCell[0],mTargetCell[1],item.spanX,item.spanY,false,
d.dragView.getDragVisualizeOffset(),d.dragView.getDragRegion());
}elseif((mDragMode==DRAG_MODE_NONE||mDragMode==DRAG_MODE_REORDER)
&&!mReorderAlarm.alarmPending()&&(mLastReorderX!=reorderX||
mLastReorderY!=reorderY)){
int[]resultSpan=newint[2];
mDragTargetLayout.performReorder((int)mDragViewVisualCenter[0],
(int)mDragViewVisualCenter[1],minSpanX,minSpanY,item.spanX,item.spanY,
child,mTargetCell,resultSpan,CellLayout.MODE_SHOW_REORDER_HINT);
// Otherwise, if we aren't adding to or creating a folder and there's no pending
// reorder, then we schedule a reorder
ReorderAlarmListenerlistener=newReorderAlarmListener(mDragViewVisualCenter,
minSpanX,minSpanY,item.spanX,item.spanY,d.dragView,child);
mReorderAlarm.setOnAlarmListener(listener);
mReorderAlarm.setAlarm(REORDER_TIMEOUT);
}
如果当前将要放置的位置已经被占据了, 则除了计算出需要移动的图标外, 还设置了一个延时器 ReorderAlarm, 这个延时器本质上是一个通过 Handler.postDelayed 的 Runnable. 设置延时的目的, 是为了给创建文件夹提供缓冲时间, 如果在这个延时时间内, 被拖拽的图标与将要放至的位置上的图标的中心距离足够近, 就会触发新文件夹的创建, 此时会取消 ReorderAlarm. 如果延时的时间到了, 而距离没有达到, 则会直接触发 ReorderAlarm, 播放图标挪动的动画.
6, 总结:
LauncherModel.java 是整个 Launcher 中最重要的一个类, 它保存有整个 Launcher 所需的全部数据结构, 可以理解为 Model 层. Launcher.java 则负责 UI 的显示, 所有图标的创建和显示都需要放到它里边去处理, 可以理解为 View 层. DragController 则实现了对拖拽事件的拦截和对滑动事件的分发, 可以理解为 Control 层. 这是基本的架构, 其他的业务需求是在此基础上, 进行搭建的.
来源: http://www.jianshu.com/p/92ed054cf87c
android launcher3,Android Launcher3 基本功能分析相关推荐
- android 时钟动态图标,Android 8.1 Launcher3实现动态指针时钟功能
本文主要实现功能,可能有不合理的地方 首先创建一个实现功能的工具里,直接上代码: import android.content.Context; import android.graphics.Bit ...
- Android 9/10 Launcher3 适配出现的问题修改
Android 10 将桌面设置图标长按出现的弹框中的电池去掉,去掉后如图: 这个主要是关于Android新功能Shortcuts的运用. Launcher3的流程: 在packages\apps\L ...
- Android动态秒针插件app,Android 8.1 Launcher3实现动态指针时钟功能
本文主要实现功能,可能有不合理的地方 首先创建一个实现功能的工具里,直接上代码: import android.content.Context; import android.graphics.Bit ...
- android app启动流程分析,Android应用开发之Android 7.0 Launcher3的启动和加载流程分析...
本文将带你了解Android应用开发Android 7.0 Launcher3的启动和加载流程分析,希望本文对大家学Android有所帮助. Android 7.0 Launcher3的启动和加载流程 ...
- Android 7.0 Launcher3的启动和加载流程分析----转载
Android 7.0 Launcher3的启动和加载流程分析,Launcher的本质就是一个普通应用,它比普通应用多配置了Category的Android:name="android ...
- Android 7.0 Launcher3的启动和加载流程分析
本文的分析基于MTK提供的Android 7.0源码,并非Google官方提供的源码,其中可能有一些小的差异,还望谅解. Launcher的本质就是一个普通应用,它比普通应用多配置了Category的 ...
- Android:通过systrace进行性能分析及使用-详细
Android:通过systrace进行性能分析 https://www.cnblogs.com/blogs-of-lxl/p/10926824.html 一.Systrace 简介 Systrace ...
- 【Android】Android源码版本
学而不思则罔,思而不学则殆 [Android]Android源码版本 1.下载manifest.git 2.checkout到不同的分支 3.源码下载地址列表 4.Android源码存在的分支 1.下 ...
- Android 7.1.2(Android N) Android系统启动流程
Android 7.1.2(Android N) Android系统启动流程 源码: system/core/rootdir/ init.rc init.zygote64.rc system/core ...
最新文章
- fabric-ca-server 配置mysql数据库,区块链(4)
- 本工作簿不能再使用其他新字体_1.2.16 EXCEL篇之关于工作表的操作合集
- 【大会】QoE也能驱动业务创新
- Java:使用Toxiproxy模拟各种连接问题
- 【转】刨根究底字符编码之三——字符编码的由来
- 《高性能MySQL》 第1章 MySQL架构与历史
- 二阶等差数列的性质及应用
- matlab2c使用c++实现matlab函数系列教程-abs函数
- matlab 子函数句柄,matlab-函数句柄程序.ppt
- 北斗导航 | 两个地面站之间的多跳卫星通信链路(附matlab代码)
- CHB-MIT波士顿儿童医院癫痫EEG脑电数据处理(一)
- [Codeforces Round #428 DIV2E (CF839E)] Mother of Dragons
- 基于证书的反垃圾邮件系统
- AR开发有哪些AR库,AR SDK
- Bootstrap3动态添加的元素tooltip不生效
- GetElementByName
- 关于MIT6.828_HW9_barriers xv6 homework9的一些问题
- mysql高级 tigger触发器 --[2]
- 技术人员如何判断靠谱的创业合伙人?
- PLSql连接Oracle时提示TNS:无监听程序的解决方法