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

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

        横行拖拽:

                              

 

         纵向拖拽的效果图:

                           

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

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

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




[java] view plaincopyprint?


  1. <span style="color:#000000;FONT-SIZE: 16px">package com.cn.daming.adapter;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.Collections;  
  5.   
  6. import android.content.Context;  
  7. import android.view.View;  
  8. import android.view.ViewGroup;  
  9. import android.widget.BaseAdapter;  
  10.   
  11. public abstract class DragAdapter extends BaseAdapter {  
  12.       
  13.     protected Context mContext;  
  14.     protected ArrayList<DragMessage> mlist;  
  15.       
  16.     public DragAdapter(Context mContext, ArrayList<DragMessage> mlist) {  
  17.         this.mContext = mContext;  
  18.         this.mlist = mlist;  
  19.     }  
  20.       
  21.     public int getCount() {  
  22.         if (this.mlist != null) {  
  23.             return this.mlist.size();  
  24.         }  
  25.         return 0;  
  26.     }  
  27.       
  28.     public DragMessage getItem(int position) {  
  29.         return (DragMessage)this.mlist.get(position);  
  30.     }  
  31.       
  32.     public long getItemId(int position) {  
  33.         return 0;  
  34.     }  
  35.       
  36.      public void addMsg(DragMessage msg){  
  37.         this.mlist.add(msg);  
  38.      }  
  39.       
  40.      final void reFlag(){  
  41.         for (DragMessage msg : this.mlist) {  
  42.           msg.flag = 0;  
  43.         }  
  44.         notifyDataSetChanged();  
  45.      }  
  46.   
  47.      final void swap(int srcPosition, int dragPosition){  
  48.         Collections.swap(this.mlist, srcPosition, dragPosition);  
  49.         notifyDataSetChanged();  
  50.      }  
  51.   
  52.      final void setFlag(int position, int flag){  
  53.         getItem(position).flag = flag;  
  54.         notifyDataSetChanged();  
  55.      }  
  56.        
  57.     public abstract View getView(int position, View convertView, ViewGroup parent);  
  58.   
  59. }  
  60. </span>  


 

  

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




[java] view plaincopyprint?


  1. package com.cn.daming.adapter;  
  2.   
  3. public class DragMessage {  
  4.      public static final int MOVE_FLAG = 1;  
  5.      public static final int STATIC_FLAG = 0;  
  6.      public int flag = 0;  
  7. }  


 

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




[java] view plaincopyprint?


  1. package com.cn.daming.adapter;  
  2.   
  3. import android.content.Context;  
  4. import android.graphics.Bitmap;  
  5. import android.graphics.Color;  
  6. import android.graphics.PixelFormat;  
  7. import android.graphics.drawable.Drawable;  
  8. import android.os.Handler;  
  9. import android.os.Looper;  
  10. import android.os.Message;  
  11. import android.util.AttributeSet;  
  12. import android.util.Log;  
  13. import android.view.Gravity;  
  14. import android.view.MotionEvent;  
  15. import android.view.View;  
  16. import android.view.ViewGroup;  
  17. import android.view.WindowManager;  
  18. import android.widget.AdapterView;  
  19. import android.widget.GridView;  
  20. import android.widget.ImageView;  
  21.   
  22. public class GragGridView extends GridView{  
  23.   
  24.     private ImageView dragImageView;//拖动item的preview  
  25.     private WindowManager windowManager;  
  26.     private WindowManager.LayoutParams windowParams;  
  27.     private int dragSrcPosition; //开始拖拽的位置    
  28.     private int dragPosition;    // 结束拖拽的位置   
  29.     private int dragPointX;//相对于item的x坐标   
  30.     private int dragPointY;//相对于item的y坐标    
  31.     private int dragOffsetX;  
  32.     private int dragOffsetY;  
  33.     private int dragImageId;  
  34.     private int itemHeight;  
  35.     private int itemWidth;  
  36.     private int moveHeight = 0;  
  37.     private int upScrollBounce;  
  38.     private int downScrollBounce;  
  39.     private int dragColor = Color.GRAY;  
  40.       
  41.     private int changePosition = -1;  
  42.     private long scrollDelayMillis = 10L;  
  43.       
  44.     private int middleX;  
  45.     private int middleY;  
  46.     private boolean isDrag = false;  
  47.       
  48.     private RefreshHandler scrollDelayUp = new RefreshHandler(Looper.getMainLooper(), true);  
  49.     private RefreshHandler scrollDelayDown = new RefreshHandler(Looper.getMainLooper(), false);  
  50.       
  51.     private int scrollHeight = 4;  
  52.     private int maxSH = 20;  
  53.     private int minSH = 4;  
  54.       
  55.     public void setMoveHeight(int height) {  
  56.         this.moveHeight = height;  
  57.     }  
  58.       
  59.     public void setDragColor(int color) {  
  60.       this.dragColor = color;  
  61.     }  
  62.       
  63.     public void setDragImageId(int id) {  
  64.         this.dragImageId = id;  
  65.     }  
  66.   
  67.     public GragGridView(Context context, AttributeSet attrs) {  
  68.         super(context, attrs);  
  69.     }  
  70.       
  71.     @Override  
  72.     public boolean onInterceptTouchEvent(MotionEvent ev) {  
  73.   
  74.         if (ev.getAction() == MotionEvent.ACTION_DOWN) {  
  75.             int x = (int)ev.getX();  
  76.             int y = (int)ev.getY();  
  77.               
  78.             this.dragSrcPosition = this.dragPosition = pointToPosition(x, y);  
  79.             if (this.dragPosition == -1) {  
  80.                 return super.onInterceptTouchEvent(ev);  
  81.             }  
  82.             ViewGroup itemView = (ViewGroup)getChildAt(this.dragPosition -   
  83.                         getFirstVisiblePosition());  
  84.             //得到当前点在item内部的偏移量 即相对于item左上角的坐标   
  85.             this.itemHeight = itemView.getHeight();  
  86.             this.dragPointX = (x - itemView.getLeft());  
  87.             this.dragPointY = (y - itemView.getTop());  
  88.             this.dragOffsetX = (int)(ev.getRawX() - x);  
  89.             this.dragOffsetY = (int)(ev.getRawY() - y);  
  90.             View dragger = itemView.findViewById(this.dragImageId);  
  91.             if ((dragger != null) && (x > dragger.getLeft()&& x < dragger.getRight()) &&   
  92.                     (y > dragger.getTop() && y < dragger.getBottom())) {  
  93.                 if(this.moveHeight <= 0 || (this.moveHeight >= getHeight()/2)) {  
  94.                     this.upScrollBounce = (getHeight() / 3);  
  95.                     this.downScrollBounce = (getHeight() * 2 / 3);  
  96.                 } else {  
  97.                     this.upScrollBounce = this.moveHeight;  
  98.                     this.downScrollBounce = (getHeight() - this.moveHeight);  
  99.                 }  
  100.                   
  101.                 //解决问题3       
  102.                 //每次都销毁一次cache,重新生成一个bitmap     
  103.                 itemView.destroyDrawingCache();   
  104.                 itemView.setDrawingCacheEnabled(true);  
  105.                 Drawable background = itemView.getBackground();  
  106.                 itemView.setBackgroundColor(this.dragColor);  
  107.                 Bitmap bitmap = Bitmap.createBitmap(itemView.getDrawingCache());  
  108.                 itemView.setBackgroundDrawable(background);  
  109.                 //建立item的缩略图   
  110.                 startDrag(bitmap, x, y);  
  111.             }  
  112.             return false;  
  113.         }  
  114.         return super.onInterceptTouchEvent(ev);  
  115.     }  
  116.   
  117.   
  118.   
  119.     @Override  
  120.     public boolean onTouchEvent(MotionEvent ev) {  
  121.           
  122.         if ((this.dragImageView != null) && (this.dragPosition != -1)) {  
  123.             int action = ev.getAction();  
  124.              int moveY = (int)ev.getY();  
  125.              int moveX = (int)ev.getX();  
  126.             switch(action) {  
  127.                   case MotionEvent.ACTION_UP:  
  128.                         int upX = (int)ev.getX();                   
  129.                         int upY = (int)ev.getY();                   
  130.                         stopDrag();                   
  131.                         onDrop(upX, upY);  
  132.                         break;  
  133.                   case MotionEvent.ACTION_MOVE:  
  134.                         if (moveX <= 0)  
  135.                           this.middleX = 0;  
  136.                         else if (moveX >= getWidth())  
  137.                           this.middleX = getWidth();  
  138.                         else {  
  139.                           this.middleX = moveX;  
  140.                         }  
  141.                           
  142.                         if (moveY <= 0)  
  143.                           this.middleY = 0;  
  144.                         else if (moveY >= getHeight())  
  145.                           this.middleY = getHeight();  
  146.                         else {  
  147.                           this.middleY = moveY;  
  148.                         }  
  149.                         dragPositionChanged();  
  150.                         onDrag(moveX, moveY);  
  151.             }  
  152.             return true;  
  153.         }  
  154.         return super.onTouchEvent(ev);  
  155.     }  
  156.   
  157.     private void onDrag(int x, int y) {  
  158.         if (this.dragImageView != null) {  
  159.             this.windowParams.alpha = 0.8F;  
  160.               
  161.             if (this.middleX - this.dragPointX <= 0)  
  162.                 this.windowParams.x = this.dragOffsetX;  
  163.             else if (this.middleX - this.dragPointX >= getWidth() - this.itemWidth)  
  164.                 this.windowParams.x = (getWidth() - this.itemWidth + this.dragOffsetX);  
  165.             else {  
  166.                 this.windowParams.x = (this.middleX - this.dragPointX + this.dragOffsetX);  
  167.             }  
  168.               
  169.             if (this.middleY - this.dragPointY <= 0)  
  170.                 this.windowParams.y = this.dragOffsetY;  
  171.             else if (this.middleY - this.dragPointY >= getHeight() - this.itemHeight)  
  172.                 this.windowParams.y = (getHeight() - this.itemHeight + this.dragOffsetY);  
  173.             else {  
  174.                 this.windowParams.y = (this.middleY - this.dragPointY + this.dragOffsetY);  
  175.             }  
  176.             this.windowManager.updateViewLayout(this.dragImageView, this.windowParams);  
  177.         }  
  178.           
  179.         int tempPosition = pointToPosition(this.middleX, this.middleY);  
  180.         Log.v("daming", "GragGridView ---> 177 tempPosition == "+tempPosition);  
  181.         if (tempPosition != -1) {  
  182.           this.dragPosition = tempPosition;  
  183.         }  
  184.           
  185.         if ((y >= this.upScrollBounce) && (y <= this.downScrollBounce)) {  
  186.             this.isDrag = false;  
  187.             return;  
  188.         }  
  189.           
  190.         if (y < this.upScrollBounce) {  
  191.             float a = this.upScrollBounce - this.middleY;  
  192.             float b = this.upScrollBounce;  
  193.             float c = a / b;  
  194.             this.scrollHeight = (int)(c * (this.maxSH - this.minSH) + this.minSH);  
  195.             this.isDrag = true;  
  196.             this.scrollDelayUp.sleep(0L);  
  197.         } else if (y > this.downScrollBounce) {  
  198.             float a = this.middleY - this.downScrollBounce;  
  199.             float b = this.upScrollBounce;  
  200.             float c = a / b;  
  201.             this.scrollHeight = (int)(c * (this.maxSH - this.minSH) + this.minSH);  
  202.             this.isDrag = true;  
  203.             this.scrollDelayDown.sleep(0L);  
  204.         }  
  205.     }  
  206.       
  207.     private void startDrag(Bitmap bm, int x, int y) {  
  208.         stopDrag();  
  209.           
  210.         this.windowParams = new WindowManager.LayoutParams();  
  211.         //Gravity.TOP|Gravity.LEFT;这个必须加   
  212.         this.windowParams.gravity = Gravity.TOP|Gravity.LEFT;  
  213.         //得到preview左上角相对于屏幕的坐标   
  214.         this.windowParams.x = (x - this.dragPointX + this.dragOffsetX);  
  215.         this.windowParams.y = (y - this.dragPointY + this.dragOffsetY);  
  216.   
  217.         //设置拖拽item的宽和高   
  218.         this.windowParams.width = WindowManager.LayoutParams.WRAP_CONTENT;       
  219.         this.windowParams.height = WindowManager.LayoutParams.WRAP_CONTENT;  
  220.         this.windowParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE                           
  221.                              | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE                           
  222.                              | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON                           
  223.                              | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;   
  224.         this.windowParams.format = PixelFormat.TRANSLUCENT;  
  225.         this.windowParams.windowAnimations = 0;  
  226.   
  227.         ImageView imageView = new ImageView(getContext());  
  228.         imageView.setImageBitmap(bm);  
  229.         this.windowManager = ((WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE));//“window”  
  230.         this.windowManager.addView(imageView, this.windowParams);  
  231.         this.dragImageView = imageView;  
  232.     }  
  233.   
  234.     private void stopDrag() {  
  235.        if (this.dragImageView != null) {  
  236.           this.windowManager.removeView(this.dragImageView);  
  237.           this.dragImageView = null;  
  238.        }  
  239.        this.changePosition = -1;  
  240.        this.isDrag = false;  
  241.     }  
  242.       
  243.     private void dragPositionChanged(){  
  244.         DragAdapter adapter = (DragAdapter)getAdapter();  
  245.         if (this.changePosition != this.dragPosition) {  
  246.           if (this.changePosition == -1)  
  247.           {  
  248.             this.changePosition = this.dragPosition;  
  249.             adapter.setFlag(this.changePosition, 1);  
  250.             return;  
  251.           }  
  252.   
  253.           adapter.swap(this.changePosition, this.dragPosition);  
  254.   
  255.           this.changePosition = this.dragPosition;  
  256.         }  
  257.     }  
  258.       
  259.     public void setMaxSH(int sh){  
  260.         this.maxSH = sh;  
  261.     }  
  262.   
  263.     public void setMinSH(int sh){  
  264.         this.minSH = sh;  
  265.     }  
  266.       
  267.     private void onDrop(int x, int y){  
  268.         //为了避免滑动到分割线的时候,返回-1的问题          
  269.         int tempPosition = pointToPosition(x, y);           
  270.         if(tempPosition!=INVALID_POSITION){               
  271.             dragPosition = tempPosition;           
  272.         }   
  273.         //超出边界处理           
  274.         if(y<getChildAt(0).getTop()){               
  275.             //超出上边界              
  276.             dragPosition = 0;           
  277.         }else if(y>getChildAt(getChildCount()-1).getBottom()||  
  278.                 (y>getChildAt(getChildCount()-1).getTop()&&x>getChildAt(getChildCount()-1).getRight())){  
  279.             //超出下边界               
  280.             dragPosition = getAdapter().getCount()-1;           
  281.         }   
  282.   
  283.         //数据交换           
  284.         if(dragPosition!=dragSrcPosition&&dragPosition>-1&&dragPosition<getAdapter().getCount()){  
  285.             DragAdapter adapter = (DragAdapter)getAdapter();  
  286.             adapter.reFlag();  
  287.         }   
  288.           
  289. //      DragAdapter adapter = (DragAdapter)getAdapter();  
  290. //      adapter.reFlag();  
  291.     }  
  292.       
  293.     private void actDown(){  
  294.         int tempPosition = pointToPosition(this.middleX, this.middleY);  
  295.         if (tempPosition != AdapterView.INVALID_POSITION) {  
  296.           this.dragPosition = tempPosition;  
  297.         }  
  298.         dragPositionChanged();  
  299.     }  
  300.       
  301.     private void actUp(){  
  302.       int tempPosition = pointToPosition(this.middleX, this.middleY);  
  303.       if (tempPosition != AdapterView.INVALID_POSITION) {  
  304.         this.dragPosition = tempPosition;  
  305.       }  
  306.       dragPositionChanged();  
  307.     }  
  308.       
  309.     class RefreshHandler extends Handler {  
  310.         boolean isUp;  
  311.   
  312.          public RefreshHandler(Looper looper, boolean isUp){  
  313.               super(looper);  
  314.               this.isUp = isUp;  
  315.          }  
  316.   
  317.          public RefreshHandler(Looper l) {  
  318.               super(l);  
  319.          }  
  320.            
  321.           public void handleMessage(Message msg){  
  322.               if (GragGridView.this.isDrag) {  
  323.                 if (this.isUp)  
  324.                     GragGridView.this.actUp();  
  325.                 else {  
  326.                     GragGridView.this.actDown();  
  327.                 }  
  328.                 sleep(GragGridView.this.scrollDelayMillis);  
  329.               }  
  330.           }  
  331.             
  332.           public void sleep(long delayMillis) {  
  333.               sendMessageDelayed(obtainMessage(0), delayMillis);  
  334.           }  
  335.     }  
  336. }  


 

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

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




[java] view plaincopyprint?


  1. <span style="color:#000000;FONT-SIZE: 16px">package com.cn.daming.draggridview;  
  2.   
  3. import java.util.ArrayList;  
  4.   
  5. import android.app.Activity;  
  6. import android.content.Context;  
  7. import android.graphics.Color;  
  8. import android.graphics.drawable.Drawable;  
  9. import android.os.Bundle;  
  10. import android.view.LayoutInflater;  
  11. import android.view.View;  
  12. import android.view.ViewGroup;  
  13. import android.widget.ImageView;  
  14. import android.widget.TextView;  
  15.   
  16. import com.cn.daming.adapter.DragAdapter;  
  17. import com.cn.daming.adapter.DragMessage;  
  18. import com.cn.daming.adapter.GragGridView;  
  19.   
  20. public class GragGridViewAppActivity extends Activity {  
  21.   
  22.     private MyAdapter myAdapter;  
  23.     private ArrayList<DragMessage> mlist = new ArrayList<DragMessage>();  
  24.     private GragGridView mGridView;  
  25.       
  26.     @Override  
  27.     public void onCreate(Bundle savedInstanceState) {  
  28.         super.onCreate(savedInstanceState);  
  29.         setContentView(R.layout.drag_grid_activity);  
  30.         initDate();  
  31.         mGridView = (GragGridView)findViewById(R.id.drag_grid);  
  32.         myAdapter = new MyAdapter(this, mlist);  
  33.         mGridView.setAdapter(myAdapter);  
  34.         //设置触发拖动的区域,用一个ImageView来设置,这个必须设置  
  35.         mGridView.setDragImageId(R.id.grag_grid_item_view);  
  36.         //以下这些都做了相应的处理,不设置没关系,而且效果也不错  
  37.         //设置拖动浮项的背景色  
  38. //      mListView.setDragColor(Color.RED);  
  39.         //设置滚动的最大像素  
  40. //      mListView.setMaxSH(sh);  
  41.         //设置滚动的最小像素  
  42. //      mListView.setMinSH(sh);  
  43.         //设置滚动区的高度(2*height应该小于ListView自己的高度)  
  44. //      mListView.setMoveHeight(height);  
  45.     }  
  46.       
  47.     private void initDate(){  
  48.         for (int i = 1; i <= 100; i++) {  
  49.             MyMessage msg = new MyMessage();  
  50.             String str = "DM_" + i;  
  51.             msg.msg = str;  
  52.             mlist.add(msg);  
  53.         }  
  54.     }  
  55.       
  56.     class MyAdapter extends DragAdapter{  
  57.           
  58.         Drawable background;  
  59.   
  60.         public MyAdapter(Context mContext, ArrayList<DragMessage> mlist) {  
  61.             super(mContext, mlist);  
  62.         }  
  63.   
  64.         @Override  
  65.         public View getView(int position, View convertView, ViewGroup parent) {  
  66.             View view = convertView;  
  67.             ViewHolder holder = null;  
  68.             if (view == null) {  
  69.                 view = LayoutInflater.from(mContext).inflate(  
  70.                         R.layout.drag_grid_item, null);  
  71.                 holder = new ViewHolder();  
  72.                 holder.tv = (TextView) view  
  73.                         .findViewById(R.id.drag_grid_item_text);  
  74.                 holder.iv = (ImageView) view  
  75.                         .findViewById(R.id.drag_grid_item_image);  
  76.                 view.setTag(holder);  
  77.             } else {  
  78.                 holder = (ViewHolder) view.getTag();  
  79.             }  
  80.             holder.tv.setText(((MyMessage)getItem(position)).msg);  
  81.             holder.iv.setBackgroundResource(R.drawable.title2);  
  82.             if(background == null){  
  83.                 background = view.getBackground();}  
  84.             if(getItem(position).flag == DragMessage.MOVE_FLAG){  
  85.                 view.setBackgroundColor(Color.GRAY);   
  86.             }  
  87.             else{  
  88.                 view.setBackgroundDrawable(background);  
  89.             }  
  90.   
  91.             return view;  
  92.         }  
  93.           
  94.     }  
  95.     private class ViewHolder {  
  96.         TextView tv;  
  97.         ImageView iv;  
  98.     }  
  99. }</span>  


 

   2.2、MyMessage.java中的代码:




[java] view plaincopyprint?


  1. <span style="color:#000000;FONT-SIZE: 16px">package com.cn.daming.draggridview;  
  2.   
  3. import com.cn.daming.adapter.DragMessage;  
  4.   
  5. public class MyMessage extends DragMessage{  
  6.     public String msg;  
  7. }  
  8. </span>  


 

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

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




[html] view plaincopyprint?


  1. <span style="color:#000000;FONT-SIZE: 16px"><?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="fill_parent"  
  4.     android:layout_height="fill_parent"  
  5.     android:orientation="vertical" >  
  6.   
  7. <com.cn.daming.adapter.GragGridView     
  8.        android:id="@+id/drag_grid"     
  9.        android:layout_width="fill_parent"     
  10.        android:layout_height="fill_parent"   
  11.        android:numColumns="auto_fit"  
  12.        android:columnWidth="70dp"  
  13.        android:stretchMode="columnWidth"  
  14.        android:gravity="center"  
  15.        android:layout_gravity="center"  
  16.        android:cacheColorHint="#00000000"/>    
  17. </LinearLayout></span>  


 

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




[html] view plaincopyprint?


  1. <span style="color:#000000;FONT-SIZE: 16px"><?xml version="1.0" encoding="utf-8"?>    
  2. <!-- 一定要使用相对布局 -->    
  3. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  4.     android:background="#FFFFFF"   
  5.     android:id="@+id/grag_grid_item_view"   
  6.     android:layout_width="fill_parent"    
  7.     android:layout_height="fill_parent">    
  8.     <TextView    
  9.        android:id="@+id/drag_grid_item_text"     
  10.        android:layout_width="wrap_content"     
  11.        android:layout_height="50dp"    
  12.        android:paddingLeft="5dip"   
  13.        android:gravity="center"  
  14.        android:textColor="#ffff00ff"  
  15.        android:layout_below="@+id/drag_grid_item_image"   
  16.        android:capitalize="none"  
  17.     />    
  18.     <ImageView   
  19.        android:id="@+id/drag_grid_item_image"  
  20.        android:layout_width="50dp"    
  21.        android:layout_height="50dp"  
  22.        android:scaleType="center"  
  23.      />  
  24. </RelativeLayout> </span>