最近看到联想,摩托罗拉等,手机launcher中有个效果,进入mainmenu后,里面的应用程序的图标可以拖来拖去,所以我也参照网上给的代码,写了一个例子。还是很有趣的,实现的流畅度没有人家的那么好,我只是模仿这种效果,我写的这个拖拽是两个图标之间进行交换,所以,当从一行的某个位置,换到下一行的另一列的时候,发现有好几个图标都改变位置了,因为是相邻两个交换位置,所以每经过相邻的图标的时候都改变位置。先弄个雏形,以后再更新优化。

转载请标明出处:http://blog.csdn.net/wdaming1986/article/details/7436881

先看几张效果图,再来研究代码:

横行拖拽:

纵向拖拽的效果图:

下面贴上代码---->在GragGridViewApp-4-7这个工程里面:

1、在包com.cn.daming.adapter中,有三个类----->

1.1、DragAdapter.java这个类中的代码如下:

package com.cn.daming.adapter;import java.util.ArrayList;import java.util.Collections;import android.content.Context;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;public abstract class DragAdapter extends BaseAdapter {protected Context mContext;protected ArrayList<DragMessage> mlist;public DragAdapter(Context mContext, ArrayList<DragMessage> mlist) {this.mContext = mContext;this.mlist = mlist;}public int getCount() {    if (this.mlist != null) {        return this.mlist.size();    }return 0;}public DragMessage getItem(int position) {return (DragMessage)this.mlist.get(position);}public long getItemId(int position) {return 0;} public void addMsg(DragMessage msg){    this.mlist.add(msg); } final void reFlag(){    for (DragMessage msg : this.mlist) {      msg.flag = 0;    }    notifyDataSetChanged(); } final void swap(int srcPosition, int dragPosition){    Collections.swap(this.mlist, srcPosition, dragPosition);    notifyDataSetChanged(); } final void setFlag(int position, int flag){    getItem(position).flag = flag;    notifyDataSetChanged(); } public abstract View getView(int position, View convertView, ViewGroup parent);}

1.2、DragMessage.java这个类中的代码如下:

package com.cn.daming.adapter;public class DragMessage { public static final int MOVE_FLAG = 1; public static final int STATIC_FLAG = 0; public int flag = 0;}

1.3、GragGridView.java核心类中的代码如下:

package com.cn.daming.adapter;import android.content.Context;import android.graphics.Bitmap;import android.graphics.Color;import android.graphics.PixelFormat;import android.graphics.drawable.Drawable;import android.os.Handler;import android.os.Looper;import android.os.Message;import android.util.AttributeSet;import android.util.Log;import android.view.Gravity;import android.view.MotionEvent;import android.view.View;import android.view.ViewGroup;import android.view.WindowManager;import android.widget.AdapterView;import android.widget.GridView;import android.widget.ImageView;public class GragGridView extends GridView{private ImageView dragImageView;//拖动item的previewprivate WindowManager windowManager;private WindowManager.LayoutParams windowParams;private int dragSrcPosition; //开始拖拽的位置  private int dragPosition;    // 结束拖拽的位置 private int dragPointX;//相对于item的x坐标 private int dragPointY;//相对于item的y坐标  private int dragOffsetX;private int dragOffsetY;private int dragImageId;private int itemHeight;private int itemWidth;private int moveHeight = 0;private int upScrollBounce;private int downScrollBounce;private int dragColor = Color.GRAY;private int changePosition = -1;private long scrollDelayMillis = 10L;private int middleX;private int middleY;private boolean isDrag = false;private RefreshHandler scrollDelayUp = new RefreshHandler(Looper.getMainLooper(), true);private RefreshHandler scrollDelayDown = new RefreshHandler(Looper.getMainLooper(), false);private int scrollHeight = 4;private int maxSH = 20;private int minSH = 4;    public void setMoveHeight(int height) {    this.moveHeight = height;}    public void setDragColor(int color) {      this.dragColor = color;    }    public void setDragImageId(int id) {    this.dragImageId = id;}public GragGridView(Context context, AttributeSet attrs) {super(context, attrs);}@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {if (ev.getAction() == MotionEvent.ACTION_DOWN) {int x = (int)ev.getX();int y = (int)ev.getY();this.dragSrcPosition = this.dragPosition = pointToPosition(x, y);if (this.dragPosition == -1) {        return super.onInterceptTouchEvent(ev);    }ViewGroup itemView = (ViewGroup)getChildAt(this.dragPosition -         getFirstVisiblePosition());//得到当前点在item内部的偏移量 即相对于item左上角的坐标 this.itemHeight = itemView.getHeight();this.dragPointX = (x - itemView.getLeft());    this.dragPointY = (y - itemView.getTop());    this.dragOffsetX = (int)(ev.getRawX() - x);    this.dragOffsetY = (int)(ev.getRawY() - y);    View dragger = itemView.findViewById(this.dragImageId);    if ((dragger != null) && (x > dragger.getLeft()&& x < dragger.getRight()) &&     (y > dragger.getTop() && y < dragger.getBottom())) {    if(this.moveHeight <= 0 || (this.moveHeight >= getHeight()/2)) {    this.upScrollBounce = (getHeight() / 3);            this.downScrollBounce = (getHeight() * 2 / 3);    } else {    this.upScrollBounce = this.moveHeight;            this.downScrollBounce = (getHeight() - this.moveHeight);    }        //解决问题3         //每次都销毁一次cache,重新生成一个bitmap       itemView.destroyDrawingCache();     itemView.setDrawingCacheEnabled(true);        Drawable background = itemView.getBackground();        itemView.setBackgroundColor(this.dragColor);        Bitmap bitmap = Bitmap.createBitmap(itemView.getDrawingCache());        itemView.setBackgroundDrawable(background);        //建立item的缩略图         startDrag(bitmap, x, y);    }    return false;}return super.onInterceptTouchEvent(ev);}@Overridepublic boolean onTouchEvent(MotionEvent ev) {if ((this.dragImageView != null) && (this.dragPosition != -1)) {int action = ev.getAction(); int moveY = (int)ev.getY();     int moveX = (int)ev.getX();switch(action) {      case MotionEvent.ACTION_UP:        int upX = (int)ev.getX();                         int upY = (int)ev.getY();                         stopDrag();                         onDrop(upX, upY);                break;          case MotionEvent.ACTION_MOVE:        if (moveX <= 0)      this.middleX = 0;    else if (moveX >= getWidth())      this.middleX = getWidth();    else {      this.middleX = moveX;    }                if (moveY <= 0)          this.middleY = 0;        else if (moveY >= getHeight())          this.middleY = getHeight();        else {          this.middleY = moveY;        }        dragPositionChanged();        onDrag(moveX, moveY);}return true;}return super.onTouchEvent(ev);}private void onDrag(int x, int y) {if (this.dragImageView != null) {this.windowParams.alpha = 0.8F;if (this.middleX - this.dragPointX <= 0)        this.windowParams.x = this.dragOffsetX;    else if (this.middleX - this.dragPointX >= getWidth() - this.itemWidth)        this.windowParams.x = (getWidth() - this.itemWidth + this.dragOffsetX);    else {        this.windowParams.x = (this.middleX - this.dragPointX + this.dragOffsetX);    }if (this.middleY - this.dragPointY <= 0)        this.windowParams.y = this.dragOffsetY;    else if (this.middleY - this.dragPointY >= getHeight() - this.itemHeight)        this.windowParams.y = (getHeight() - this.itemHeight + this.dragOffsetY);    else {        this.windowParams.y = (this.middleY - this.dragPointY + this.dragOffsetY);    }this.windowManager.updateViewLayout(this.dragImageView, this.windowParams);}int tempPosition = pointToPosition(this.middleX, this.middleY);Log.v("daming", "GragGridView ---> 177 tempPosition == "+tempPosition);    if (tempPosition != -1) {      this.dragPosition = tempPosition;    }        if ((y >= this.upScrollBounce) && (y <= this.downScrollBounce)) {        this.isDrag = false;        return;    }        if (y < this.upScrollBounce) {        float a = this.upScrollBounce - this.middleY;        float b = this.upScrollBounce;        float c = a / b;        this.scrollHeight = (int)(c * (this.maxSH - this.minSH) + this.minSH);        this.isDrag = true;        this.scrollDelayUp.sleep(0L);    } else if (y > this.downScrollBounce) {        float a = this.middleY - this.downScrollBounce;        float b = this.upScrollBounce;        float c = a / b;        this.scrollHeight = (int)(c * (this.maxSH - this.minSH) + this.minSH);        this.isDrag = true;        this.scrollDelayDown.sleep(0L);    }}private void startDrag(Bitmap bm, int x, int y) {stopDrag();this.windowParams = new WindowManager.LayoutParams();//Gravity.TOP|Gravity.LEFT;这个必须加 this.windowParams.gravity = Gravity.TOP|Gravity.LEFT;//得到preview左上角相对于屏幕的坐标     this.windowParams.x = (x - this.dragPointX + this.dragOffsetX);    this.windowParams.y = (y - this.dragPointY + this.dragOffsetY);    //设置拖拽item的宽和高     this.windowParams.width = WindowManager.LayoutParams.WRAP_CONTENT;         this.windowParams.height = WindowManager.LayoutParams.WRAP_CONTENT;    this.windowParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE                                                  | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE                                                  | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON                                                  | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;     this.windowParams.format = PixelFormat.TRANSLUCENT;    this.windowParams.windowAnimations = 0;    ImageView imageView = new ImageView(getContext());    imageView.setImageBitmap(bm);    this.windowManager = ((WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE));//“window”    this.windowManager.addView(imageView, this.windowParams);    this.dragImageView = imageView;}private void stopDrag() {   if (this.dragImageView != null) {      this.windowManager.removeView(this.dragImageView);      this.dragImageView = null;   }   this.changePosition = -1;   this.isDrag = false;}private void dragPositionChanged(){    DragAdapter adapter = (DragAdapter)getAdapter();    if (this.changePosition != this.dragPosition) {      if (this.changePosition == -1)      {        this.changePosition = this.dragPosition;        adapter.setFlag(this.changePosition, 1);        return;      }      adapter.swap(this.changePosition, this.dragPosition);      this.changePosition = this.dragPosition;    }}public void setMaxSH(int sh){    this.maxSH = sh;}public void setMinSH(int sh){    this.minSH = sh;}private void onDrop(int x, int y){//为了避免滑动到分割线的时候,返回-1的问题        int tempPosition = pointToPosition(x, y);         if(tempPosition!=INVALID_POSITION){             dragPosition = tempPosition;         } //超出边界处理         if(y<getChildAt(0).getTop()){             //超出上边界            dragPosition = 0;         }else if(y>getChildAt(getChildCount()-1).getBottom()||(y>getChildAt(getChildCount()-1).getTop()&&x>getChildAt(getChildCount()-1).getRight())){//超出下边界             dragPosition = getAdapter().getCount()-1;         } //数据交换         if(dragPosition!=dragSrcPosition&&dragPosition>-1&&dragPosition<getAdapter().getCount()){DragAdapter adapter = (DragAdapter)getAdapter();adapter.reFlag();} //    DragAdapter adapter = (DragAdapter)getAdapter();//    adapter.reFlag();}private void actDown(){    int tempPosition = pointToPosition(this.middleX, this.middleY);    if (tempPosition != AdapterView.INVALID_POSITION) {      this.dragPosition = tempPosition;    }    dragPositionChanged();}private void actUp(){  int tempPosition = pointToPosition(this.middleX, this.middleY);  if (tempPosition != AdapterView.INVALID_POSITION) {    this.dragPosition = tempPosition;  }  dragPositionChanged();}class RefreshHandler extends Handler {boolean isUp; public RefreshHandler(Looper looper, boolean isUp){      super(looper);      this.isUp = isUp; } public RefreshHandler(Looper l) {      super(l); }   public void handleMessage(Message msg){      if (GragGridView.this.isDrag) {        if (this.isUp)        GragGridView.this.actUp();        else {        GragGridView.this.actDown();        }        sleep(GragGridView.this.scrollDelayMillis);      }  }    public void sleep(long delayMillis) {      sendMessageDelayed(obtainMessage(0), delayMillis);  }}}


2、在包com.cn.daming.draggridview中,有两个类---->

2.1、GragGridViewAppActivity.java入口类中的代码:

package com.cn.daming.draggridview;import java.util.ArrayList;import android.app.Activity;import android.content.Context;import android.graphics.Color;import android.graphics.drawable.Drawable;import android.os.Bundle;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.ImageView;import android.widget.TextView;import com.cn.daming.adapter.DragAdapter;import com.cn.daming.adapter.DragMessage;import com.cn.daming.adapter.GragGridView;public class GragGridViewAppActivity extends Activity {private MyAdapter myAdapter;private ArrayList<DragMessage> mlist = new ArrayList<DragMessage>();private GragGridView mGridView;@Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.drag_grid_activity);        initDate();        mGridView = (GragGridView)findViewById(R.id.drag_grid);        myAdapter = new MyAdapter(this, mlist);        mGridView.setAdapter(myAdapter);        //设置触发拖动的区域,用一个ImageView来设置,这个必须设置        mGridView.setDragImageId(R.id.grag_grid_item_view);        //以下这些都做了相应的处理,不设置没关系,而且效果也不错        //设置拖动浮项的背景色//      mListView.setDragColor(Color.RED);        //设置滚动的最大像素//      mListView.setMaxSH(sh);        //设置滚动的最小像素//      mListView.setMinSH(sh);        //设置滚动区的高度(2*height应该小于ListView自己的高度)//      mListView.setMoveHeight(height);    }private void initDate(){    for (int i = 1; i <= 100; i++) {MyMessage msg = new MyMessage();String str = "DM_" + i;msg.msg = str;mlist.add(msg);}    }    class MyAdapter extends DragAdapter{        Drawable background;public MyAdapter(Context mContext, ArrayList<DragMessage> mlist) {super(mContext, mlist);}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {View view = convertView;ViewHolder holder = null;if (view == null) {view = LayoutInflater.from(mContext).inflate(R.layout.drag_grid_item, null);holder = new ViewHolder();holder.tv = (TextView) view.findViewById(R.id.drag_grid_item_text);holder.iv = (ImageView) view        .findViewById(R.id.drag_grid_item_image);view.setTag(holder);} else {holder = (ViewHolder) view.getTag();}holder.tv.setText(((MyMessage)getItem(position)).msg);holder.iv.setBackgroundResource(R.drawable.title2);if(background == null){background = view.getBackground();}if(getItem(position).flag == DragMessage.MOVE_FLAG){view.setBackgroundColor(Color.GRAY); }else{view.setBackgroundDrawable(background);}return view;}        }    private class ViewHolder {TextView tv;ImageView iv;}}

2.2、MyMessage.java中的代码:

package com.cn.daming.draggridview;import com.cn.daming.adapter.DragMessage;public class MyMessage extends DragMessage{public String msg;}


3、布局文件layout有两个----->

3.1、drag_grid_activity.xml中的代码如下:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:orientation="vertical" ><com.cn.daming.adapter.GragGridView          android:id="@+id/drag_grid"          android:layout_width="fill_parent"          android:layout_height="fill_parent"        android:numColumns="auto_fit"       android:columnWidth="70dp"       android:stretchMode="columnWidth"       android:gravity="center"       android:layout_gravity="center"       android:cacheColorHint="#00000000"/>  </LinearLayout>

3.2、drag_grid_item.xml中的代码如下:

<?xml version="1.0" encoding="utf-8"?>  <!-- 一定要使用相对布局 -->  <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:background="#FFFFFF" android:id="@+id/grag_grid_item_view"     android:layout_width="fill_parent"      android:layout_height="fill_parent">      <TextView         android:id="@+id/drag_grid_item_text"          android:layout_width="wrap_content"          android:layout_height="50dp"         android:paddingLeft="5dip"        android:gravity="center"       android:textColor="#ffff00ff"       android:layout_below="@+id/drag_grid_item_image"        android:capitalize="none"    />      <ImageView        android:id="@+id/drag_grid_item_image"       android:layout_width="50dp"         android:layout_height="50dp"       android:scaleType="center"     /></RelativeLayout>  

有问题的可以留言,欢迎大家来讨论研究,分享知识,共同进步!

以下是我在开发中遇到问题的参考资料:

http://www.cnblogs.com/qianxudetianxia/archive/2011/06/19/2084886.html

http://lipeng88213.iteye.com/blog/1099621

http://hi.baidu.com/jwq359699768/blog/item/f2caee8741e71131c75cc369.html

源代码下载地址:http://download.csdn.net/detail/wdaming1986/4207350

更多相关文章

  1. Android自动化单元测试(上)
  2. Android仿360卫士布局风格
  3. 学习android, 自己编的一个黑白棋游戏 (提供源代码下载)
  4. 新建Android(安卓)AVD,点击start、launch,出现进度条后无任何反应,
  5. android调用震动的例子
  6. Android实现双向滑动特效的实例代码
  7. 说说Android桌面(Launcher应用)背后的故事(六)——研究Launcher
  8. Android(安卓)完整地操作数据库--日记本实例
  9. 浅浅的介绍一下android里面Handler、Looper、Message和MessageQu

随机推荐

  1. 控件:ExpandableListView --- 树型组件
  2. android(3)
  3. Android图形系统之Surface、SurfaceView
  4. android 手机传感器
  5. 在Android平台上加载本地库的危险性
  6. Android 蓝牙难点总结
  7. android网络抓包相关
  8. DataBinding绑定android:onClick出错
  9. Android中短信的广播接收问题
  10. Android中定义接口的用法