之前在網上看到有篇文章:Launcher之Dock細節篇http://www.linuxidc.com/Linux/2011-09/44160.htm 它實現了一個仿Mac的dock。感覺蠻有意思的,所以就照著仿製了一個。
可以動態添加捷徑,預設包含AllApp按鈕,表徵圖置中顯示。
DockBar上的表徵圖可以相互交換位置,並且將表徵圖拖拽出去。
拖拽釋放後:
文章後邊附帶的源碼是基於Android2.2內建的launcher2稍作修改而成,使用eclipse調試。
一、首先要在Launcher的setupViews函數裡面初始化自己的layout(需增加3個地方)
1、
// hmg add for dock { dockbar = (DockBar) dragLayer.findViewById(R.id.dockbar); dockbar.setLauncher(this); dockbar.setDragController(dragController); // hmg add for dock }
2、
dragController.setDragScoller(workspace); dragController.setDragListener(deleteZone); dragController.setDockDragListener(dockbar); // hmg25 add for dock dragController.setScrollView(dragLayer); dragController.setMoveTarget(workspace);
setDockDragListener為自訂函數,添加在DragController的startDrag中,具體見源碼
//hmg25 add for dock { if(mDockListener!=null){ mDockListener.onDragStart(source, dragInfo, dragAction); } //hmg25 add for dock }
3、
// The order here is bottom to top. dragController.addDropTarget(workspace); dragController.addDropTarget(dockbar); // hmg25 add for dock dragController.addDropTarget(deleteZone);
二、在layout-port的launcher.xml中增加
<!-- hmg25 add for dock { --> <com.xuxm.demo.launcher.DockBar android:id="@+id/dockbar" android:layout_width="fill_parent" android:layout_height="@dimen/button_bar_height" android:layout_gravity="bottom|center_horizontal" android:background="@drawable/dock_bg" launcher:direction="horizontal"> <HorizontalScrollView android:id="@+id/dock_scroll_view" android:scrollbars="none" android:fadingEdge="none" android:saveEnabled="false" android:layout_width="fill_parent" android:layout_height="fill_parent"> <LinearLayout android:orientation="horizontal" android:id="@+id/dock_item_holder" android:saveEnabled="false" android:layout_width="fill_parent" android:layout_height="fill_parent"> <com.xuxm.demo.launcher.HandleView android:id="@+id/all_apps_button" android:layout_centerHorizontal="true" android:src="@drawable/hotseat_all_apps" launcher:direction="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent" android:focusable="true" android:clickable="true" /> </LinearLayout> </HorizontalScrollView></com.xuxm.demo.launcher.DockBar> <!-- hmg25 add for dock } -->
三、建立自訂的類:
package com.xuxm.demo.launcher;import android.content.Context;import android.graphics.Rect;import android.util.AttributeSet;import android.util.Log;import android.view.Gravity;import android.view.View;import android.widget.FrameLayout;import android.widget.LinearLayout;public class DockBar extends LinearLayout implements DropTarget, DragSource,DragController.DragListener,View.OnLongClickListener{private Launcher mLauncher; private DragController mDragController; private Workspace mWorkspace; private View mDragView; private LinearLayout mItemHolder; private View mScrollView; private View mSelectedView;public DockBar(Context context){ super(context); // TODO Auto-generated constructor stub} public DockBar(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onFinishInflate() { // TODO Auto-generated method stub Log.i("hmg", "DockBar->onFinishInflate"); mItemHolder = (LinearLayout)findViewById(R.id.dock_item_holder); mScrollView= findViewById(R.id.dock_scroll_view); super.onFinishInflate(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // TODO Auto-generated method stub super.onMeasure(widthMeasureSpec, heightMeasureSpec); //置中顯示 FrameLayout.LayoutParams lp= (FrameLayout.LayoutParams)mItemHolder.getLayoutParams(); lp.gravity=Gravity.CENTER; mItemHolder.setLayoutParams(lp); postInvalidate(); requestLayout(); } @Override public boolean onLongClick(View v) {// TODO Auto-generated method stub if (mLauncher.isAllAppsVisible()) mLauncher.closeAllApps(false); mSelectedView = v; mDragController.startDrag(v, this, v.getTag(), DragController.DRAG_ACTION_MOVE); removeSelectedItem(); return true; } private void removeSelectedItem() { if (mSelectedView == null) return; mItemHolder.removeView(mSelectedView); }@Overridepublic void onDragStart(DragSource source, Object info, int dragAction) {// TODO Auto-generated method stubLog.i("hmg", "DockBar->onDragStart");}@Overridepublic void onDragEnd() {// TODO Auto-generated method stub}@Overridepublic void setDragController(DragController dragger) {// TODO Auto-generated method stubmDragController = dragger;}void setLauncher(Launcher launcher) {mLauncher = launcher;}void setWorkspace(Workspace workspace ){mWorkspace=workspace;}@Overridepublic void onDropCompleted(View target, boolean success) {// TODO Auto-generated method stub}/* * 拖拽釋放時響應 */ @Override public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset, DragView dragView, Object dragInfo) { int position=0; position=getLocation(x); //根據釋放時的座標,擷取插入位置 addItemAt((ItemInfo)dragInfo, position); }@Overridepublic void onDragEnter(DragSource source, int x, int y, int xOffset,int yOffset, DragView dragView, Object dragInfo) {// TODO Auto-generated method stubLog.i("hmg", "DockBar->onDragEnter");setBackgroundResource(R.drawable.dock_bg_press); }@Overridepublic void onDragOver(DragSource source, int x, int y, int xOffset,int yOffset, DragView dragView, Object dragInfo) {// TODO Auto-generated method stub}private void addItemAt(ItemInfo itemInfo, int position) {View view=null;switch (itemInfo.itemType) {case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:ShortcutInfo shortcutInfo;// 拖拽表徵圖來自於app listif(itemInfo.container ==NO_ID&& itemInfo instanceof ApplicationInfo) {//與來自案頭的表徵圖包含資訊不一樣,具體看源碼shortcutInfo= new ShortcutInfo((ApplicationInfo)itemInfo);}elseshortcutInfo = (ShortcutInfo)itemInfo; //拖拽表徵圖來自案頭//調用Launcher中的createSmallShortcut產生一個imageViewview = mLauncher.CreateDockShortcut(shortcutInfo);view.setOnLongClickListener(this);break;case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER:break;default:throw new IllegalStateException("Unknown item type: "+ itemInfo.itemType);} mItemHolder.addView(view, position); }/* * 傳入x座標,判斷新表徵圖的位置,此處僅判斷豎屏 */ public int getLocation(int x){ for(int i=0;i<mItemHolder.getChildCount();i++){ View iv = mItemHolder.getChildAt(i); int[] position = new int[2]; //擷取座標,如果要適應橫屏可以稍作修改,比較Y值 iv.getLocationOnScreen(position); //判斷釋放時新增的表徵圖在原表徵圖的之前還是之後 if(x<=(position[0]+(iv.getWidth()/2))){ return i; } } return mItemHolder.getChildCount(); } @Overridepublic void onDragExit(DragSource source, int x, int y, int xOffset,int yOffset, DragView dragView, Object dragInfo) {// TODO Auto-generated method stubsetBackgroundResource(R.drawable.dock_bg); mItemHolder.removeView(mDragView);Log.i("hmg", "DockBar->onDragExit");}@Overridepublic boolean acceptDrop(DragSource source, int x, int y, int xOffset,int yOffset, DragView dragView, Object dragInfo) {// TODO Auto-generated method stub//接受什麼類型的表徵圖 Log.i("hmg", "DockBar->acceptDrop");final ItemInfo item = (ItemInfo) dragInfo; if (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET || item.itemType == LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER || item.itemType == LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER || item.itemType == LauncherSettings.Favorites.ITEM_TYPE_WIDGET_PHOTO_FRAME || item.itemType == LauncherSettings.Favorites.ITEM_TYPE_WIDGET_SEARCH || item.itemType == LauncherSettings.Favorites.ITEM_TYPE_WIDGET_CLOCK) { return false; } return true; }@Overridepublic Rect estimateDropLocation(DragSource source, int x, int y,int xOffset, int yOffset, DragView dragView, Object dragInfo,Rect recycle) {// TODO Auto-generated method stubreturn null;} }
參考資料:
《Android開發:為launcher添加一個仿Mac的Dock(附源碼)》