之前在网上看到有篇文章: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);
}
@Override
public void onDragStart(DragSource source, Object info, int dragAction) {
// TODO Auto-generated method stub
Log.i("hmg", "DockBar->onDragStart");
}
@Override
public void onDragEnd() {
// TODO Auto-generated method stub
}
@Override
public void setDragController(DragController dragger) {
// TODO Auto-generated method stub
mDragController = dragger;
}
void setLauncher(Launcher launcher) {
mLauncher = launcher;
}
void setWorkspace(Workspace workspace )
{
mWorkspace=workspace;
}
@Override
public 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);
}
@Override
public void onDragEnter(DragSource source, int x, int y, int xOffset,
int yOffset, DragView dragView, Object dragInfo) {
// TODO Auto-generated method stub
Log.i("hmg", "DockBar->onDragEnter");
setBackgroundResource(R.drawable.dock_bg_press);
}
@Override
public 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 list
if(itemInfo.container ==NO_ID&& itemInfo instanceof ApplicationInfo)
{
//与来自桌面的图标包含信息不一样,具体看源码
shortcutInfo= new ShortcutInfo((ApplicationInfo)itemInfo);
}
else
shortcutInfo = (ShortcutInfo)itemInfo; //拖拽图标来自桌面
//调用Launcher中的createSmallShortcut生成一个imageView
view = 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();
}
@Override
public void onDragExit(DragSource source, int x, int y, int xOffset,
int yOffset, DragView dragView, Object dragInfo) {
// TODO Auto-generated method stub
setBackgroundResource(R.drawable.dock_bg);
mItemHolder.removeView(mDragView);
Log.i("hmg", "DockBar->onDragExit");
}
@Override
public 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;
}
@Override
public Rect estimateDropLocation(DragSource source, int x, int y,
int xOffset, int yOffset, DragView dragView, Object dragInfo,
Rect recycle) {
// TODO Auto-generated method stub
return null;
}
}
参考资料: