必威电竞|足球世界杯竞猜平台

launcher
來源:互聯(lián)網(wǎng)

Launcher即安卓桌面(Home)程序,是Android 系統(tǒng)中的桌面啟動(dòng)器,是桌面UI的統(tǒng)稱。其較早期的版本為L(zhǎng)auncher,較新的版本為L(zhǎng)auncher2。

Launcher2程序的包名為com.android.launcher,使用了LOCAL_CERTIFICATE :=shared簽名,并且增加了一些所使用的許可(使用標(biāo)簽)和限制調(diào)用者的許可(使用標(biāo)簽)。其程序的核心是一個(gè)Activity。

2017年,微軟將其安卓桌面啟動(dòng)器Arrow Launcher改名為Microsoft Launcher。2020年8月,微軟推出Launcher6.2版本,支持Android 7系統(tǒng)及更高版本。

基本信息

Launcher是安卓系統(tǒng)中的桌面啟動(dòng)器,安卓系統(tǒng)的桌面UI統(tǒng)稱為L(zhǎng)auncher。Launcher是安卓系統(tǒng)中的主要程序組件之一,安卓系統(tǒng)中如果沒有Launcher就無法啟動(dòng)安卓桌面,Launcher出錯(cuò)的時(shí)候,安卓系統(tǒng)會(huì)出現(xiàn)“進(jìn)程 com.android.launcher 意外停止”的提示窗口。這時(shí)需要重新啟動(dòng)Launcher。

主要文件

1.Launcher.java:launcher中主要的activity。

2.DragLayer.java:launcher layout的rootview。DragLayer實(shí)際上也是一個(gè)抽象的界面,用來處理拖動(dòng)和對(duì)事件進(jìn)行初步處理然后按情況分發(fā)下去,角色是一個(gè)controller。它首先用onInterceptTouchEvent(MotionEvent)來攔截所有的touch事件,如果是長(zhǎng)按item拖動(dòng)的話不把事件傳下去,直接交由onTouchEvent()處理,這樣就可以實(shí)現(xiàn)item的移動(dòng)了,如果不是拖動(dòng)item的話就把事件傳到目標(biāo)視圖,交有目標(biāo)view的事件處理函數(shù)做相應(yīng)處理。如果有要對(duì)事件的特殊需求的話可以修改onInterceptTouchEvent(MotionEvent)來實(shí)現(xiàn)所需要的功能。

3. DragController.java:為Drag定義的一個(gè)接口。包含一個(gè)接口,兩個(gè)方法和兩個(gè)靜態(tài)常量。接口為DragListener(包含onDragStart(),onDragEnd()兩個(gè)函數(shù)),onDragStart()是在剛開始拖動(dòng)的時(shí)候被調(diào)用,onDragEnd()是在拖動(dòng)完成時(shí)被調(diào)用。在launcher中典型的應(yīng)用是DeleteZone,在長(zhǎng)按拖動(dòng)item時(shí)調(diào)用onDragStart()顯示,在拖動(dòng)結(jié)束的時(shí)候onDragEnd()隱藏。兩個(gè)函數(shù)包括startDrag()和setDragItemInfo().startDrag()用于在拖動(dòng)是傳遞要拖動(dòng)的item的信息以及拖動(dòng)的方式,setDragItemInfo()用于傳遞item的參數(shù)信息(包括位置以及大小)。兩個(gè)常量為DRAG_ACTION_MOVE,DRAG_ACTION_COPY來標(biāo)識(shí)拖動(dòng)的方式,DRAG_ACTION_MOVE為移動(dòng),表示在拖動(dòng)的時(shí)候需要?jiǎng)h除原來的item,DRAG_ACTION_COPY為復(fù)制型的拖動(dòng),表示保留被拖動(dòng)的item。

4.LauncherModel.java:輔助的文件。里面有許多封裝的對(duì)數(shù)據(jù)庫(kù)的操作。包含幾個(gè)線程,其中最主要的是ApplicationsLoader和DesktopItemsLoader。ApplicationsLoader在加載所有應(yīng)用程序時(shí)使用,DesktopItemsLoader在加載workspace的時(shí)候使用。其他的函數(shù)就是對(duì)數(shù)據(jù)庫(kù)的封裝,比如在刪除,替換,添加程序的時(shí)候做更新數(shù)據(jù)庫(kù)和UI的工作。

5.Workspace.java:抽象的桌面。由N個(gè)celllayout組成,從cellLayout更高一級(jí)的層面上對(duì)事件的處理。

6.LauncherProvider.java:launcher的數(shù)據(jù)庫(kù),里面存儲(chǔ)了桌面的item的信息。在創(chuàng)建數(shù)據(jù)庫(kù)的時(shí)候會(huì)loadFavorites(db)方法,loadFavorites()會(huì)解析XML目錄下的default_workspace.xml文件,把其中的內(nèi)容讀出來寫到數(shù)據(jù)庫(kù)中,這樣就做到了桌面的預(yù)制。

7.CellLayout.java:組成workspace的視圖,繼承自viewgroup,既是一個(gè)dragSource,又是一個(gè)dropTarget,可以將它里面的item拖出去,也可以容納拖動(dòng)過來的item。在workspace_screen里面定了一些它的view參數(shù)。

8.ItemInfo.java:對(duì)item的抽象,所有類型item的父類,item包含的屬性有id(標(biāo)識(shí)item的id),cellX(在橫向位置上的位置,從0開始),cellY(在縱向位置上的位置,從0開始),spanX(在橫向位置上所占的單位格),spanY(在縱向位置上所占的單位格),screen(在workspace的第幾屏,從0開始),itemType(item的類型,有widget,search,application等),container(item所在的)。

9.UserFolder.java:用戶創(chuàng)建的文件夾。可以將item拖進(jìn)文件夾,單擊時(shí)打開文件夾,長(zhǎng)按文件夾上面標(biāo)題處可以重命名文件夾。

10.LiveFolder.java:系統(tǒng)自帶的文件夾。從系統(tǒng)中創(chuàng)建出的如聯(lián)系人的文件夾等。

11.DeleteZone:刪除框。在平時(shí)是出于隱藏狀態(tài),在將item長(zhǎng)按拖動(dòng)的時(shí)候會(huì)顯示出來,如果將item拖動(dòng)到刪除框位置時(shí)會(huì)刪除item。DeleteZone實(shí)現(xiàn)了DropTarget和DragListener兩個(gè)接口。

12.LauncherSettings.java:字符串的定義。數(shù)據(jù)庫(kù)項(xiàng)的字符串定義,另外在這里定義了container的類型,還有itemType的定義,除此還有一些特殊的widget(如search,clock的定義等)的類型定義。

補(bǔ)充Launcher工程中的類:

主要模塊

1.界面模型:

Launcher的界面的rootview是DragLayer,它是一個(gè)FrameLayout,在它上面workspace(應(yīng)該說是celllayout)占了絕大部分的空間,celllayout的參數(shù)文件是workspace_screen.XML。workspace既是一個(gè)DropTarget又是一個(gè)DragSource,可以從AllAppGridView中拖出應(yīng)用程序放在它上面,也可以把它里面的item拖走刪除或者拖到bottombar里面去。

(對(duì)于想修改launcher的同學(xué),可以自定義DragLayer.java,比如改為AbsoluteLayout等,再修改launcher.xml布局文件,就可以實(shí)現(xiàn)各種樣式的launcher界面。)

2.Drop& Drag模型:

⒉1 DragSource:可以拖動(dòng)的對(duì)象來源的容器,在launcher中主要有AllAppGridView,workspace等。

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

⒉2 DropTarget:可以放置被拖動(dòng)的對(duì)象的容器。在launcher中有folder,workspace,bottombar等,一個(gè)View既可以是Dragsource也可以是DropTarget。主要包含以下幾個(gè)接口:

1) boolean acceptDrop(DragSource source,int x,int y,int xOffset,int yOffset,Object dragInfo);

acceptDrop 函數(shù)用來判斷dropTarget是否可以接受item放置在自己里面。

2) void onDragEnter(DragSource source,int x,int y,int xOffset,int yOffset,Object dragInfo);

onDragEnter是item被拖動(dòng)進(jìn)入到一個(gè)dropTarget的時(shí)候的回調(diào)。

3) void onDragOver(DragSource source,int x,int y,int xOffset,int yOffset,Object dragInfo);

onDragOver是item在上一次位置和這一次位置所處的dropTarget相同的時(shí)候的回調(diào)。

4) void onDragExit(DragSource source,int x,int y,int xOffset,int yOffset,Object dragInfo);

onDragExit是item被拖出dropTarget時(shí)的回調(diào)。

5) boolean onDrop(DragSource source,int x,int y,int xOffset,int yOffset,Object dragInfo);

onDrop是item被放置到dropTarget時(shí)的回調(diào)。

函數(shù)的調(diào)用模式為:

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

if(dropTarget != null) {

/**

* 當(dāng)這一次的 target 跟上一次相同時(shí),根據(jù)坐標(biāo)來移動(dòng)item

*/

if(mLastDropTarget == dropTarget) {

dropTarget.onDragOver(mDragSource,coordinates,coordinates,

{( int) mTouchOffsetX,( int) mTouchOffsetY,mDragInfo);

} else{

/**

* 當(dāng)上一次的位置跟這一次不同而且上一次的位置不為空,說明item移 *動(dòng)出了,將上次的 視圖 根據(jù)上次的坐標(biāo)重新排列,并根據(jù)當(dāng)前坐標(biāo)重排*當(dāng)前的*/

if(mLastDropTarget != null) {

mLastDropTarget.onDragExit(mDragSource,coordinates,coordinates,

( int) mTouchOffsetX,( int) mTouchOffsetY,mDragInfo);

}

dropTarget.onDragEnter(mDragSource,coordinates,coordinates,

( int) mTouchOffsetX,( int) mTouchOffsetY,mDragInfo);

}

} else{//如果這一次為 null,上一次不為 null,那么把上一次坐標(biāo)位置的 cell 去掉

if(mLastDropTarget != null) {

mLastDropTarget.onDragExit(mDragSource,coordinates,coordinates,

( int) mTouchOffsetX,( int) mTouchOffsetY,mDragInfo);

}

}

//記錄上次的droptarget

mLastDropTarget = dropTarget;

3.Touch event總結(jié):

由于launcher的事件比較多比較復(fù)雜,所以在事件處理的時(shí)候一般采用rootview先用onInterceptTouchEvent(MotionEvent)攔截所有的touch事件,經(jīng)過判斷后分發(fā)給childview。

判斷的規(guī)則如下:

a.down事件首先會(huì)傳遞到onInterceptTouchEvent()方法

b.如果該ViewGroup的onInterceptTouchEvent()在接收到down事件處理完成之后returnfalse,那么后續(xù)的move,up等事件將繼續(xù)會(huì)先傳遞給該ViewGroup,之后才和down事件一樣傳遞給最終的目標(biāo)view的onTouchEvent()處理。

c.如果該ViewGroup的onInterceptTouchEvent()在接收到down事件處理完成之后returntrue,那么后續(xù)的move,up等事件將不再傳遞給onInterceptTouchEvent(),而是和down事件一樣傳遞給該ViewGroup的onTouchEvent()處理,注意,目標(biāo)視圖將接收不到任何事件。

d.如果最終需要處理事件的view的onTouchEvent()返回了false,那么該事件將被傳遞至其上一層次的view的onTouchEvent()處理。

e.如果最終需要處理事件的view 的onTouchEvent()返回了true,那么后續(xù)事件將可以繼續(xù)傳遞給該view的onTouchEvent()處理。

解決方式

1.將所有的應(yīng)用都排列在桌面上

將所有的應(yīng)用都排列在桌面是通過首先創(chuàng)建一個(gè)三維的boolean型全局?jǐn)?shù)組來記錄item的排列情況,第一維是屏數(shù),第二維是縱向上的排列情況,第三維是橫向的排列情況,如果那個(gè)位置被item所占用就標(biāo)記為1,否則標(biāo)記為0.在啟動(dòng)時(shí)把全局?jǐn)?shù)組初始化為0,然后在添加的時(shí)候把相應(yīng)的位置置1.凡是涉及到workspace上item的變化,比如移動(dòng)、添加、刪除操作時(shí)都需要維護(hù)數(shù)組,保持?jǐn)?shù)組的正確性,因?yàn)樵诎惭b新程序時(shí)依據(jù)數(shù)組的狀態(tài)去判斷把item加到什么位置。

2.動(dòng)態(tài)增加屏幕

動(dòng)態(tài)增加屏幕是通過worksapce .addchild(view)的方式實(shí)現(xiàn)。基本思路是:首先預(yù)先規(guī)定所允許的最大的屏幕數(shù),然后在需要增加屏幕而且當(dāng)前屏幕數(shù)沒有超過最大屏幕數(shù)的時(shí)候通過(CellLayout)mInflater.inflate(R.layout.workspace_screen,null)創(chuàng)建一個(gè)celllayout實(shí)例出來,然后通過addchild把它加入進(jìn)去。在屏幕上的item被刪除時(shí)通過從最后一屏起判斷屏幕上是否有item,如果有的話保留,沒有的話則刪除最后一屏,以此類推。

3.預(yù)制桌面

a.添加普通的應(yīng)用程序快捷方式:

在../res/XML下的default_workspace.xml文件中加入默認(rèn)要放置的普通的應(yīng)用程序。加入的格式為:

launcher:packageName="... " //應(yīng)用的packageName

launcher:className="... " //應(yīng)用啟動(dòng)時(shí)的第一個(gè)activity

launcher:screen="..." //放置在第幾屏(放在workspace的時(shí)候需要,從0開始,0為第一屏,1為第二屏,以此類推...)

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

launcher:y="..." /> //放置y方向的位置(在行中的位置)

packageName和className可以通過點(diǎn)擊程序,然后在打印出的log中找到comp={...},例如如下信息:

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

workspace的布局如下:

b.添加widget:

在../package/apps/VLauncher/res/XML下的default_workspace.xml文件中加入默認(rèn)要放置的普通的應(yīng)用程序。加入的格式為:

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

launcher:className=" ..."http://實(shí)現(xiàn) widget的 receiver 類的名稱.

launcher:集裝箱="..."http://放置的位置(只能為desktop)

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

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

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

launcher:spanx="..."http://在x方向上所占格數(shù)

launcher:spany="..."/> //在y方向上所占格數(shù)

例如,要在第3屏的第一行第二列放置開始放置一個(gè)x方向上占兩個(gè)單位格,y方向上占兩個(gè)單位格的時(shí)鐘,可以加入以下代碼:

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

launcher:集裝箱="desktop"

launcher:screen="2"

launcher:x="1"

launcher:y="0"

launcher:spanx="2"

launcher:spany="2"/>

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

要修改桌面的排列方式,如下,先根據(jù)橫豎屏設(shè)置修改workspace_screen.XML里shortAxisCells和longAxisCells的參數(shù),然后在Launcher.java中修改NUMBER_CELLS_X和NUMBER_CELLS_Y的值,在2.3版本中剛開始往數(shù)據(jù)庫(kù)中添加item的時(shí)候會(huì)去判斷,如果不修改NUMBER_CELLS_X和NUMBER_CELLS_Y的話會(huì)導(dǎo)致一部分的item顯示不出來,導(dǎo)致預(yù)制apk的失敗。

5.增加worksapce上的屏數(shù)

要增加屏數(shù),首先在根據(jù)橫豎屏在launcher.XML中的;,然后在Launcher.java中修改screen_計(jì)數(shù)的值即可。

xml文件

1.workspace_screen.xml

launcher:cellWidth="95dip"cell(即item)的寬

launcher:cellHeight="93dip"cell(即item)的寬

launcher:longAxisStartPadding="25dip"

較長(zhǎng)(屏幕的寬和高中較大的那一方向,根據(jù)橫豎屏方向有所不同)方向上距離起點(diǎn)的像素?cái)?shù)

launcher:longAxisEndPadding="55dip"

較長(zhǎng)(屏幕的寬和高中較大的那一方向,根據(jù)橫豎屏方向有所不同)方向上距離終點(diǎn)的像素?cái)?shù)

launcher:shortAxisStartPadding="20dip"

較短(屏幕的寬和高中較大的那一方向,根據(jù)橫豎屏方向有所不同)方向上距離起點(diǎn)的像素?cái)?shù)

launcher:shortAxisEndPadding="120dip"

較短(屏幕的寬和高中較大的那一方向,根據(jù)橫豎屏方向有所不同)方向上距離起點(diǎn)的像素?cái)?shù)

launcher:shortAxisCells="3"

較短的方向上可以容納的cell的數(shù)量

launcher:longAxisCells="5"

較長(zhǎng)的方向上可以容納的cell的數(shù)量

shortAxisCells和longAxisCells決定一個(gè)workspace(即CellLayout)上可以容納的item的個(gè)數(shù)為shortAxisCells*longAxisCells.

2. application_boxed.XML

所有應(yīng)用程序和系統(tǒng)文件夾中item的定義。

3.application.xml

Workspace的item的layout定義。

參考資料 >

..2024-02-04

Microsoft Launcher.microsoft.2024-02-06

微軟改名 Arrow Android 啟動(dòng)器發(fā)布 Microsoft Launcher.livesino.2024-02-06

微軟Microsoft Launcher 6.2正式發(fā)布 新增橫屏模式.中華網(wǎng).2024-02-06

Android_launcher的源碼詳細(xì)分析.CSDN.2012-07-08

生活家百科家居網(wǎng)