我是靠谱客的博主 愉快书包,最近开发中收集的这篇文章主要介绍android launcher分析和修改10,Android Launcher分析和修改9——Launcher启动APP流程(转载)...,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

出处 : http://www.cnblogs.com/mythou/p/3187881.html

本来想分析AppsCustomizePagedView类,不过今天突然接到一个临时任务。客户反馈说机器界面的图标很难点击启动程序,经常点击了没有反应,Boss说要优先解决这问题。没办法,只能看看是怎么回事。今天分析一下Launcher启动APP的过程。从用户点击到程序启动的流程,下面针对WorkSpace上的快捷图标点击启动流程进行分析。(如果分不清WorkSpace是什么或者不知道快捷方式和其他图标区别,请看我前面的Launcher分析文章)

PS:新建的QQ群,有兴趣可以加入一起讨论:Android群:322599434

下面我们先看看Launcher启动APP的大概流程:

a4c26d1e5885305701be709a3d33442f.png

(鉴于很多转载文章的人把作者信息都删除了,只能在图片上加入水印,不会给大家阅读造成影响)

上面就是手指触摸屏幕开始,到点击响应的流程。Launcher里面因为有滑动、拖曳、点击等手势操作,所以区分了很多流程判断。最后调用Launcher.java里面的onClick()方法响应点击,启动程序。下面我们针对关键流程做分析。

1、WorkSpace触摸

前面我们分析Launcher的配置文件时就说过,Launcher外面的界面主要就是通过WorkSpace来显示的。它是一个ViewGroup的自定义类。下面我们先看看WorkSpace的onInterceptTouchEvent做了什么。

//Edited by mythou

//http://www.cnblogs.com/mythou/

public boolean onInterceptTouchEvent(MotionEvent ev)

{

if(OWL_DEBUG) Log.d(OWL, "onInterceptTouchEvent enter");

//对ACTION_DOWN和ACTION_UP做一些标记处理。

switch (ev.getAction() & MotionEvent.ACTION_MASK)

{

case MotionEvent.ACTION_DOWN:

mXDown = ev.getX();

mYDown = ev.getY();

break;

case MotionEvent.ACTION_POINTER_UP:

case MotionEvent.ACTION_UP:

if (mTouchState == TOUCH_STATE_REST)

{

final CellLayout currentPage = (CellLayout)

getChildAt(mCurrentPage);

if (!currentPage.lastDownOnOccupiedCell())

{

onWallpaperTap(ev);

}

}

}

if(OWL_DEBUG) Log.d(OWL, "onInterceptTouchEvent call super

InterceptTouch");

//调用父类的onInterceptTouchEvent,这里是调用了SmoothPagedView

return super.onInterceptTouchEvent(ev);

}

在WorkSpace里面并没有拦截消息,主要是调用父类的方法,也就是PagedView的onInterceptTouchEvent()方法。因为WorkSpace的直接父类SmoothPagedView也是继承了PagedView类,有关PagedView的onInterceptTouchEvent()方法,我在前面的文章已经分析过。这里不做多说,不了解的朋友可以看看(点这里)。

2、CellLayout的onInterceptTouchEvent()方法

CellLayout也是一个继承了ViewGroup的类,主要用来显示桌面控件。刚开始分析Launcher的时候,我们分析配置文件的时候也说过WorkSpace就是由5个CellLayout组成的。因此我们点击WorkSpace里面图标的时候,自然会调用CellLayout里面的东西。CellLayout里面的onInterceptTouchEvent()做的事情并不多:

//Edited by mythou

//http://www.cnblogs.com/mythou/

public boolean onInterceptTouchEvent(MotionEvent ev)

{

if(OWL_DEBUG) Log.d(OWL, "onInterceptTouchEvent enter");

final int action = ev.getAction();

if (action == MotionEvent.ACTION_DOWN)

{

//清除所有触摸标记

clearTagCellInfo();

}

//mInterceptTouchListener是WorkSpace的onTouch方法回调,下面会分析

//掌握这点很重要,因为onInterceptTouchEvent的返回值直接决定了触摸事件的传递方向

mythou

if (mInterceptTouchListener != null &&

mInterceptTouchListener.onTouch(this, ev))

{

//截断Touch传输,直接处理 ,返回true会直接调用onTouchEvent处理。 mythou

if(OWL_DEBUG) Log.d(OWL, "onInterceptTouchEvent return true

Intercept msg");

return true;

}

if (action == MotionEvent.ACTION_DOWN)

{

setTagToCellInfoForPoint((int) ev.getX(), (int) ev.getY());

}

if(OWL_DEBUG) Log.d(OWL, "onInterceptTouchEvent return

false");

//注意这里返回的是false

,onInterceptTouchEvent的返回值决定了触摸事件的传递方式。mythou

return false;

}

这里需要注意的是onInterceptTouchEvent()的返回值,如果是返回true,触摸消息会直接被CellLayout的onTouchEvent()处理,一般点击启动程序返回的都是false,因为消息最后是TextView处理(workspace上的快捷方式都是TextView的子类)。Android的触摸消息传递机制和消息拦截机制,需要好好理解好才能明白Launcher的触摸事件处理。因为个人觉得Launcher里面事件处理层次还是比较多,如果对Android的事件传递机制理解不深,就很难理解Launcher的事件处理。如果对这方面不了解的朋友,可以查查网上相关资料。后面有空我也会写一篇深入分析Android触摸事件处理的文章。

3、WorkSpace的onTouch()事件

WorkSpace里面还处理了onTouch事件,这里的onTouch事件是因为WorkSpace使用了View.OnTouchListener接口,所以实现了onTouch事件的回调。

public boolean onTouch(View v, MotionEvent event)

{

return(isSmall() || !isFinishedSwitchingState());

}

onTouch里面其实没做什么事情,就是根据两个方法返回值,判断onTouch是返回false还是返回true,返回值是什么决定了触摸事件的传递方向,上面已经说过了。这里的onTouch是给WorkSpace里面的装载的View使用的,也就是CellLayout。我们可以看看每次调用WorkSpace的onChildViewAdded()方法,会设置CellLayout的onTouch监听器。

//Edited by mythou

//http://www.cnblogs.com/mythou/

public void onChildViewAdded(View parent, View child) { if (!(child instanceof CellLayout))

{

throw new IllegalArgumentException("A Workspace can only have CellLayout children."); }

CellLayout cl = ((CellLayout) child);

//设置onTouch的监听器,CellLayout的onInterceptTouchEvent()方法会根据onTouch监听器判断是否需要拦截onTouch事件。

cl.setOnInterceptTouchListener(this);

cl.setClickable(true);

cl.setContentDescription(getContext().getString(

R.string.workspace_description_format, getChildCount()));

}

上面第二点CellLayout的onInterceptTouchEvent()方法的分析里面,return ture的时候,判断的依据mInterceptTouchListener和mInterceptTouchListener.onTouch()方法的返回值就是从这里设置的,他们也就是调用了WorkSpace的onTouch方法。

4、BubbleTextView

BubbleTextView是继承了TextView的子类,在Launcher里面所有的WorkSpace的快捷方式都是使用BubbleTextView绘画的,它的作用相当于一个按钮。在分析BubbleTextView的触摸响应前,我们先看看Launcher里面如何创建快捷方式。前面的文章我分析过Launcher加载界面数据的流程,不过没有仔细分析如何创建相关对象,下面我们先看看WorkSpace的快捷方式如何创建:

//Edited by mythou

//http://www.cnblogs.com/mythou/

View createShortcut(int layoutResId, ViewGroup parent, ShortcutInfo info)

{

BubbleTextView favorite = (BubbleTextView) mInflater.inflate(layoutResId, parent, false);

favorite.applyFromShortcutInfo(info, mIconCache);

//注意这里设置了onClickListener OWL

favorite.setOnClickListener(this);

return favorite;

}

上面就是创建快捷方式的方法,这里面我们需要注意的是,BubbleTextView调用了SetOnClickListener()方法,设置点击监听器。监听器的回调函数就是Launcher.java类里面的onCLick方法。因为Launcher类继承了View.OnClickListener接口,当然Launcher里面还继承了其他的接口,例如触摸、长按的Listener。下面我们先看看BUbbleTextView的onTouchEvent方法:

//Edited by mythou

//http://www.cnblogs.com/mythou/

public boolean onTouchEvent(MotionEvent event)

{

// 调用TextView的onToucEvent方法,主要是获取返回值,这个返回值作用很大,会响应点击事件的回调。

// 可以把这返回值打印出来看看。当点击启动程序时,这里肯定会返回true。

//原因上面已经说了很多次,这里不再啰嗦 OWL

boolean result = super.onTouchEvent(event);

switch (event.getAction()) {

case MotionEvent.ACTION_DOWN:

//下面这里主要是根据触摸状态值,做快捷方式的状态显示,例如是否需要显示按下状态。

if (mPressedOrFocusedBackground == null) {

mPressedOrFocusedBackground = createGlowingOutline(

mTempCanvas, mPressedGlowColor, mPressedOutlineColor);

}

if (isPressed())

{

mDidInvalidateForPressedState = true;

setCellLayoutPressedOrFocusedIcon();

} else {

mDidInvalidateForPressedState = false;

}

mLongPressHelper.postCheckForLongPress();

break;

case MotionEvent.ACTION_CANCEL:

case MotionEvent.ACTION_UP:

if (!isPressed()) {

mPressedOrFocusedBackground = null;

}

//这里根据状态判断是否取消长按的触摸

mLongPressHelper.cancelLongPress();

break;

}

//返回值十分重要,直接影响是否会掉用onCLick方法。

return result;

}

上面就是BubbleTextView的onTouchEvent的方法,上面强调很多次返回值,这里如果是点击流程,会返回true。然后执行onClick方法。

5、onClick()方法

最后点击会调用Launcher里面的onClick方法,不管你是点击快捷方式、文件夹、还是AllAPP的按钮,都是从这里响应回调。

//Edited by mythou

//http://www.cnblogs.com/mythou/

public void onClick(View v) {

//..........

Object tag = v.getTag();

if (tag instanceof ShortcutInfo) {

//这里点击打开我们上面分析的快捷方式图标。打开的方式也是调用startActivity,

// 只是这里调用的startActivitySafely对startActivity进行了封装 mythou

final Intent intent = ((ShortcutInfo) tag).intent;

int[] pos = new int[2];

v.getLocationOnScreen(pos);

intent.setSourceBounds(new Rect(pos[0], pos[1],

pos[0] + v.getWidth(), pos[1] + v.getHeight()));

boolean success = startActivitySafely(v, intent, tag);

if (success && v instanceof BubbleTextView) {

mWaitingForResume = (BubbleTextView) v;

mWaitingForResume.setStayPressed(true);

}

//文件夹点击响应

} else if (tag instanceof FolderInfo) {

if (v instanceof FolderIcon) {

FolderIcon fi = (FolderIcon) v;

handleFolderClick(fi);

}

//AllAPP按钮点击响应

} else if (v == mAllAppsButton) {

if (isAllAppsVisible()) {

最后

以上就是愉快书包为你收集整理的android launcher分析和修改10,Android Launcher分析和修改9——Launcher启动APP流程(转载)...的全部内容,希望文章能够帮你解决android launcher分析和修改10,Android Launcher分析和修改9——Launcher启动APP流程(转载)...所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(55)

评论列表共有 0 条评论

立即
投稿
返回
顶部