Android学习系列(12)--App列表之拖拽GridView

根据前面文章中ListView拖拽的实现原理,我们也是很容易实现推拽GridView的,下面我就以相同步骤实现基本的GridView拖拽效果。
     因为GridView不用做分组处理,代码处理起来更简洁,而且原理前面已经讲解清楚了,代码中只是简单的过下,必要的地方简单的注释一下。
1.主界面DragGridActivity.

  1. public class DragGridActivity extends Activity {
  2.     
  3.     private static List<String> list = null;
  4.     //自定义适配器
  5.     private DragGridAdapter adapter = null;
  6.     
  7.     @Override
  8.     public void onCreate(Bundle savedInstanceState) {
  9.         super.onCreate(savedInstanceState);
  10.         setContentView(R.layout.drag_grid_activity);
  11.         
  12.         initData();
  13.         
  14.         //后面用到的自定义GridView
  15.         DragGridView dragGridView = (DragGridView)findViewById(R.id.drag_grid);
  16.         adapter = new DragGridAdapter(this, list);
  17.         dragGridView.setAdapter(adapter);
  18.     }
  19.     
  20.     public void initData(){
  21.         //数据结果
  22.         list = new ArrayList<String>();
  23.         
  24.         for(int i=0; i<12; i++){
  25.             list.add("grid_"+i%12);
  26.         }
  27.     }
  28. }
复制代码

2.主界面UI布局drag_grid_activity.xml.

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3.     android:orientation="vertical"
  4.     android:layout_width="fill_parent"
  5.     android:layout_height="fill_parent"
  6.     android:background="#ffffff"
  7.     android:padding="10dip"
  8.     >
  9.     <com.fengjian.test.DragGridView 
  10.         android:id="@+id/drag_grid" 
  11.         android:layout_width="fill_parent" 
  12.         android:layout_height="wrap_content"
  13.         android:cacheColorHint="#00000000"
  14.         android:numColumns="3" 
  15.         android:stretchMode="columnWidth"
  16.         android:verticalSpacing="5dip"
  17.         android:horizontalSpacing="20dip"
  18.         android:background="#ffffff"/>
  19. </LinearLayout>
复制代码

3.列表项布局drag_grid_item.xml.

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3.     android:layout_width="fill_parent"
  4.     android:layout_height="wrap_content"
  5.     android:paddingLeft="5dip"
  6.     android:paddingRight="5dip">
  7.     <ImageView android:id="@+id/drag_grid_item_image"
  8.        android:src="@drawable/grid_icon"
  9.        android:layout_margin="5dip"
  10.        android:layout_alignParentTop="true"
  11.        android:layout_width="fill_parent"
  12.        android:layout_height="wrap_content"/>
  13.     <ImageView android:id="@+id/drag_grid_item_drag"
  14.        android:src="@drawable/grid_drag"
  15.        android:layout_alignParentTop="true"
  16.        android:layout_alignParentRight="true"
  17.        android:layout_width="wrap_content"
  18.        android:layout_height="wrap_content"/>
  19. </RelativeLayout>
复制代码

4.自定义适配器DragGridAdapter,继承ArrayAdapter<String>.

  1. public static class DragGridAdapter extends ArrayAdapter<String>{
  2.         public DragGridAdapter(Context context, List<String> objects) {
  3.             super(context, 0, objects);
  4.         }
  5.         public List<String> getList(){
  6.             return list;
  7.         }
  8.         @Override
  9.         public View getView(int position, View convertView, ViewGroup parent) {
  10.             View view = convertView;
  11.             if(view==null){
  12.                 view = LayoutInflater.from(getContext()).inflate(R.layout.drag_grid_item, null);
  13.             }
  14.             
  15.             try {
  16.                 //根据文件名获取资源文件夹中的图片资源
  17.                 Field f= (Field)R.drawable.class.getDeclaredField(getItem(position));
  18.                 int i=f.getInt(R.drawable.class);
  19.                 ImageView imageview= (ImageView)view.findViewById(R.id.drag_grid_item_image);
  20.                 imageview.setImageResource(i);
  21.             } catch (SecurityException e) {
  22.                 e.printStackTrace();
  23.             } catch (NoSuchFieldException e) {
  24.                 e.printStackTrace();
  25.             } catch (IllegalArgumentException e) {
  26.                 e.printStackTrace();
  27.             } catch (IllegalAccessException e) {
  28.                 e.printStackTrace();
  29.             }
  30.             return view;
  31.         }
  32.     }
复制代码

5.自定义视图类DragGridView,继承GridView.

  1. public class DragGridView extends GridView {
  2.     //定义基本的成员变量
  3.     private ImageView dragImageView;
  4.     private int dragSrcPosition;
  5.     private int dragPosition;
  6.     //x,y坐标的计算
  7.     private int dragPointX;
  8.     private int dragPointY;
  9.     private int dragOffsetX;
  10.     private int dragOffsetY;
  11.     
  12.     private WindowManager windowManager;
  13.     private WindowManager.LayoutParams windowParams;
  14.     
  15.     private int scaledTouchSlop;
  16.     private int upScrollBounce;
  17.     private int downScrollBounce;
  18.     
  19.     public DragGridView(Context context, AttributeSet attrs) {
  20.         super(context, attrs);
  21.     }
  22. }
复制代码

6. 重写触控拦截事件方法onInterceptTouchEvent(). 

  1. @Override
  2. public boolean onInterceptTouchEvent(MotionEvent ev) {
  3.     if(ev.getAction()==MotionEvent.ACTION_DOWN){
  4.         int x = (int)ev.getX();
  5.         int y = (int)ev.getY();
  6.         
  7.         dragSrcPosition = dragPosition = pointToPosition(x, y);
  8.         if(dragPosition==AdapterView.INVALID_POSITION){
  9.             return super.onInterceptTouchEvent(ev);
  10.         }
  11.         ViewGroup itemView = (ViewGroup) getChildAt(dragPosition-getFirstVisiblePosition());
  12.         dragPointX = x - itemView.getLeft();
  13.         dragPointY = y - itemView.getTop();
  14.         dragOffsetX = (int) (ev.getRawX() - x);
  15.         dragOffsetY = (int) (ev.getRawY() - y);
  16.         
  17.         View dragger = itemView.findViewById(R.id.drag_grid_item_drag);
  18.         //如果选中拖动图标
  19.         if(dragger!=null&&dragPointX>dragger.getLeft()&&dragPointX<dragger.getRight()&&dragPointY>dragger.getTop()&&dragPointY<dragger.getBottom()+20){
  20.             upScrollBounce = Math.min(y-scaledTouchSlop, getHeight()/4);
  21.             downScrollBounce = Math.max(y+scaledTouchSlop, getHeight()*3/4);
  22.             
  23.             itemView.setDrawingCacheEnabled(true);
  24.             Bitmap bm = Bitmap.createBitmap(itemView.getDrawingCache());
  25.             startDrag(bm, x, y);
  26.         }
  27.         return false;
  28.      }
  29.      return super.onInterceptTouchEvent(ev);
  30. }
复制代码

  startDrag和stopDrag方法如下:

  1. public void startDrag(Bitmap bm, int x, int y){
  2.     stopDrag();
  3.     
  4.     windowParams = new WindowManager.LayoutParams();
  5.     windowParams.gravity = Gravity.TOP|Gravity.LEFT;
  6.     windowParams.x = x - dragPointX + dragOffsetX;
  7.     windowParams.y = y - dragPointY + dragOffsetY;
  8.     windowParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
  9.     windowParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
  10.     windowParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
  11.                         | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
  12.                         | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
  13.                         | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
  14.     windowParams.format = PixelFormat.TRANSLUCENT;
  15.     windowParams.windowAnimations = 0;
  16.     ImageView imageView = new ImageView(getContext());
  17.     imageView.setImageBitmap(bm);
  18.     windowManager = (WindowManager)getContext().getSystemService("window");
  19.     windowManager.addView(imageView, windowParams);
  20.     dragImageView = imageView;
  21. }
  22. public void onDrag(int x, int y){
  23.     if(dragImageView!=null){
  24.         windowParams.alpha = 0.8f;
  25.         windowParams.x = x - dragPointX + dragOffsetX;
  26.         windowParams.y = y - dragPointY + dragOffsetY;
  27.         windowManager.updateViewLayout(dragImageView, windowParams);
  28.     }
  29.     int tempPosition = pointToPosition(x, y);
  30.     if(tempPosition!=INVALID_POSITION){
  31.         dragPosition = tempPosition;
  32.     }
  33.     
  34.     //滚动
  35.     if(y<upScrollBounce||y>downScrollBounce){
  36.         //使用setSelection来实现滚动
  37.         setSelection(dragPosition);
  38.     }        
  39. }
复制代码

7.重写onTouchEvent()方法. 

  1. @Override
  2. public boolean onTouchEvent(MotionEvent ev) {
  3.     if(dragImageView!=null&&dragPosition!=INVALID_POSITION){
  4.         int action = ev.getAction();
  5.         switch(action){
  6.             case MotionEvent.ACTION_UP:
  7.                 int upX = (int)ev.getX();
  8.                 int upY = (int)ev.getY();
  9.                 stopDrag();
  10.                 onDrop(upX,upY);
  11.                 break;
  12.             case MotionEvent.ACTION_MOVE:
  13.                 int moveX = (int)ev.getX();
  14.                 int moveY = (int)ev.getY();
  15.                 onDrag(moveX,moveY);
  16.                 break;
  17.             default:break;
  18.         }
  19.         return true;
  20.     }
  21.     return super.onTouchEvent(ev);
  22. }
复制代码

其中onDrag方法如下:

  1. public void onDrag(int x, int y){
  2.     if(dragImageView!=null){
  3.         windowParams.alpha = 0.8f;
  4.         windowParams.x = x - dragPointX + dragOffsetX;
  5.         windowParams.y = y - dragPointY + dragOffsetY;
  6.         windowManager.updateViewLayout(dragImageView, windowParams);
  7.     }
  8.     int tempPosition = pointToPosition(x, y);
  9.     if(tempPosition!=INVALID_POSITION){
  10.         dragPosition = tempPosition;
  11.     }
  12.     
  13.     //滚动
  14.     if(y<upScrollBounce||y>downScrollBounce){
  15.         //使用setSelection来实现滚动
  16.         setSelection(dragPosition);
  17.     }        
  18. }
复制代码

8.放下影像,数据更新。
在onDrop方法中实现:

  1. public void onDrop(int x, int y){
  2.         
  3.         //为了避免滑动到分割线的时候,返回-1的问题
  4.         int tempPosition = pointToPosition(x, y);
  5.         if(tempPosition!=INVALID_POSITION){
  6.             dragPosition = tempPosition;
  7.         }
  8.         
  9.         //超出边界处理
  10.         if(y<getChildAt(0).getTop()){
  11.             //超出上边界
  12.             dragPosition = 0;
  13.         }else if(y>getChildAt(getChildCount()-1).getBottom()||(y>getChildAt(getChildCount()-1).getTop()&&x>getChildAt(getChildCount()-1).getRight())){
  14.             //超出下边界
  15.             dragPosition = getAdapter().getCount()-1;
  16.         }
  17.         
  18.         //数据交换
  19.         if(dragPosition!=dragSrcPosition&&dragPosition>-1&&dragPosition<getAdapter().getCount()){
  20.             DragGridAdapter adapter = (DragGridAdapter)getAdapter();
  21.             String dragItem = adapter.getItem(dragSrcPosition);
  22.             adapter.remove(dragItem);
  23.             adapter.insert(dragItem, dragPosition);
  24.             Toast.makeText(getContext(), adapter.getList().toString(), Toast.LENGTH_SHORT).show();
  25.         }
  26.         
  27.     }
复制代码


      这篇文章也算是前面文章的一个补充和扩展。

posted @ 2014-03-18 08:55  xiaochao1234  阅读(704)  评论(2编辑  收藏  举报