Launcher是Android系統的"桌面",在android2.1之前采用的是launcher,android2.2之後采用的launcher2,他們之間最大的區別是launcher2有3D效果,不過launcher2整個系統的代碼的改動還是比較大的。
相關閱讀 : Android開發:為launcher添加一個仿Mac的Dock(附源碼) http://www.linuxidc.com/Linux/2011-09/44161.htm
首先來介紹下launcher目錄下的幾個文件吧,我做簡單說明:
AddAdapter:添加桌面元素的適配器。
AllAppsGridView:Icon列表的的主界面,繼承gridView。
DeleteZone:luancher的刪除區域,繼承ImageView。
DragController:拖動控制接口。
DragLayer:整個launcher的父節點,繼承FrameLayout,實現接口DrayController。
DragSource:拖動源接口,定義了void onDropCompleted(View target, boolean success)。
DropTarget:拖動目標,定義很多拖動過程需要的方法:onDrop,onDragEnter,onDragOver,onDragExit,acceptDrop。
HandleView:launcher抽屜的開關,不過在android2.2已經沒用抽屜了。
Launcher:整個launcher的程序的入口,代碼量最大的一個文件。
Workspace:整個界面layout,幾個窗口就是他下面的子節點。
我需要改動的就是模仿Mac系統,在桌面的底部加一個icon的列表功能,而且要求是把icon拖入拖出,首先上一張已經做出來的效果圖:
我首先列出我完成的幾個主要源文件:
DockProvider:持久化dock Item的元素。
DockSettings:dock一些元素和uri信息。
DockView:顯示icon的布局,繼承LinearLayout實現DropTarget,DragSource, DragController.DragListener,OnClickListener, View.OnLongClickListener接口。
我在這裡主要說下,實現原理,DockView是主要文件,它繼承LinearLayout是為了它裡面的元素水平擺放,直接用addView繼承實現,繼承系統的那些接口都是為了,接收到icon拖動的狀態和信息。
首先要在Launcher的setupViews函數裡面初始化自己的layout,代碼如下:
private void setupViews() { mDragLayer = (DragLayer) findViewById(R.id.drag_layer); final DragLayer dragLayer = mDragLayer; mWorkspace = (Workspace) dragLayer.findViewById(R.id.workspace); final Workspace workspace = mWorkspace; /*mDrawer = (SlidingDrawer) dragLayer.findViewById(R.id.drawer); final SlidingDrawer drawer = mDrawer;*/ mAllAppsGrid = (AllAppsGridView) dragLayer.findViewById(R.id.content); dock_view=(DockView)dragLayer.findViewById(R.id.dock_view); dock_view.setLauncher(this); dock_view.setDragger(mDragLayer); dock_view.init(); //mAllAppsGrid.setVisibility(View.GONE); final AllAppsGridView grid = mAllAppsGrid; final DeleteZone deleteZone = (DeleteZone) dragLayer.findViewById(R.id.delete_zone); mHandleView = (HandleView) dragLayer.findViewById(R.id.all_apps); mHandleView.setLauncher(this); //mHandleIcon = (TransitionDrawable) mHandleView.getDrawable(); //mHandleIcon.setCrossFadeEnabled(true); //author:jezz main_apps=(RelativeLayout)dragLayer.findViewById(R.id.main_apps); home=(ImageView)dragLayer.findViewById(R.id.all_home); main_apps.setVisibility(View.GONE); mHandleView.setOnClickListener(new OnClickListener() { public void onClick(View v) { onMainOpened(true); } }); home.setOnClickListener(new OnClickListener() { public void onClick(View v) { onMainClosed(true); } }); /*drawer.lock(); final DrawerManager drawerManager = new DrawerManager(); drawer.setOnDrawerOpenListener(drawerManager); drawer.setOnDrawerCloseListener(drawerManager); drawer.setOnDrawerScrollListener(drawerManager);*/ grid.setTextFilterEnabled(false); grid.setDragger(dragLayer); grid.setLauncher(this); workspace.setOnLongClickListener(this); workspace.setDragger(dragLayer); workspace.setLauncher(this); deleteZone.setLauncher(this); deleteZone.setDragController(dragLayer); deleteZone.setHandle(mHandleView); dragLayer.setIgnoredDropTarget(grid); dragLayer.setDragScoller(workspace); dragLayer.setDragListener(deleteZone); dragLayer.setDockDragListener(dock_view); dock_view.setWorkspace(workspace); }
DragLayer添加觸發的事件:
if (mListener != null) { mListener.onDragStart(v, source, dragInfo, dragAction); } if(mDockListener!=null){ mDockListener.onDragStart(v, source, dragInfo, dragAction); }
以上兩個細節地址,還有很多細節都要改,如你的dock區域是不讓用戶拖入的,所以在底部區別你要創建一個Rect,讓這個Rect區域為禁用,再就是有個細節的地方注意:當用戶卸載程序的時候你的icon也要跟著一起刪除,不過他已經寫好了,ApplicationsIntentReceiver,你在其中加下你的刪除邏輯就可以了。