android Launcher源码解析03:仿Mac的Dock

       之前在网上看到有篇文章: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;
	}   
	  
  
}

参考资料:

Android开发:为launcher添加一个仿Mac的Dock(附源码)

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值