DragGridViewEx.java文件:
  
package com.smiling.draggridview;/* * onInterceptTouchEvent() -> onItemLongClick() -> onTouchEvent()->ACTION_MOVE->ACTION_UP; *  * */import android.content.Context;import android.graphics.Bitmap;import android.graphics.Color;import android.util.AttributeSet;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;
  
//以下为自定义GridView控件;public class DragGridViewEx extends GridView{private WindowManager windowManager;// windows窗口控制类private WindowManager.LayoutParams windowParams;// 用于控制拖拽项的显示的参数private ImageView dragImageView;// 被拖拽的项(item),其实就是一个ImageView\private View  itemView=null;private Bitmap bm;private ImageView imageView;private View dragger;private int dragSrcPosition;// 手指拖动项在列表中的原始位置private int dragPosition;// 手指点击准备拖动的时候,当前拖动项在列表中的位置.private int dragPointX;private int dragPointY;// 在当前数据项中的位置private int dragOffsetX;private int dragOffsetY;// 当前视图和屏幕的距离(这里只使用了y方向上)private int upScrollBounce;// 拖动的时候,开始向上滚动的边界private int downScrollBounce;// 拖动的时候,开始向下滚动的边界private int tempChangeId;private boolean isDoTouch = false;private boolean hasAdd=false;//=========================================================================================================public DragGridViewEx(Context context) {super(context);// TODO 自动生成的构造函数存根}public DragGridViewEx(Context context, AttributeSet attrs) {super(context, attrs);// TODO 自动生成的构造函数存根}public DragGridViewEx(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);// TODO 自动生成的构造函数存根}//==========================================================================================================public void setDoTouch(boolean b){this.isDoTouch=b;this.hasAdd=false;}@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) { {if (ev.getAction() == MotionEvent.ACTION_DOWN) {{int x = (int) ev.getX();int y = (int) ev.getY();this.tempChangeId=dragSrcPosition = dragPosition = pointToPosition(x, y);System.out.println("getY()="+y+","+"dragPosition="+dragPosition);System.out.println("getFirstVisiblePosition()="+getFirstVisiblePosition());// 无效不进行处理if (dragPosition == AdapterView.INVALID_POSITION) {return super.onInterceptTouchEvent(ev);}// 获取当前位置的视图(可见状态)itemView = getChildAt(dragPosition-getFirstVisiblePosition());dragPointX = x - itemView.getLeft();dragPointY = y - itemView.getTop();   //不可见的项不算;dragOffsetX = (int) (ev.getRawX() - x);dragOffsetY = (int) (ev.getRawY() - y);//每个项中可能有其他的文字之类的东西,所以要获取 R.id.drag_gridview_image;dragger = itemView.findViewById(R.id.drag_gridview_image);if (dragger != null &&dragPointX>dragger.getLeft()            &&dragPointX<dragger.getRight()            &&dragPointY>dragger.getTop()            &&dragPointY<dragger.getBottom()) {upScrollBounce = getHeight() / 4;      // 取得向上滚动的边际,大概为该控件的1/3downScrollBounce = getHeight() * 3 / 4;// 取得向下滚动的边际,大概为该控件的2/3System.out.println("Here....");itemView.setDrawingCacheEnabled(true);// 开启cache.        bm= Bitmap.createBitmap(itemView.getDrawingCache());// 根据cache创建一个新的bitmap对象.startDrag(bm, x, y);// 初始化影像;}}}}return super.onInterceptTouchEvent(ev);}private void startDrag(Bitmap bm, int x, int y) {// stopDrag();/*** * 初始化window. */windowParams = new WindowManager.LayoutParams();windowParams.gravity = Gravity.TOP| Gravity.LEFT;windowParams.x = x - dragPointX + dragOffsetX;windowParams.y = y - dragPointY + dragOffsetY;    //getTop()+dragOffset;windowParams.width = WindowManager.LayoutParams.WRAP_CONTENT;windowParams.height = WindowManager.LayoutParams.WRAP_CONTENT;windowParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE// 不需获取焦点| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE// 不需接受触摸事件| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON// 保持设备常开,并保持亮度不变。| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;// 窗口占满整个屏幕,忽略周围的装饰边框(例如状态栏)。此窗口需考虑到装饰边框的内容。windowParams.windowAnimations = 0;imageView = new ImageView(getContext());imageView.setImageBitmap(bm);windowManager = (WindowManager) getContext().getSystemService("window");//windowManager.addView(imageView, windowParams);  //注意不在这里添加;dragImageView = imageView;}//===========================================================================================================/** * 触摸事件处理 */@Overridepublic boolean onTouchEvent(MotionEvent ev) {// item的view不为空,且获取的dragPosition有效if (dragImageView!=null&&dragPosition != INVALID_POSITION && isDoTouch==true) {if(!this.hasAdd){windowManager.addView(imageView, windowParams);this.hasAdd=true;}int action = ev.getAction();switch (action) {case MotionEvent.ACTION_UP:System.out.println("ACTION_UP");if(!this.dragger.isShown()){this.dragger.setVisibility(View.VISIBLE);System.out.println("VISIBLE");}int upX = (int) ev.getX();int upY = (int) ev.getY();stopDrag();onDrop(upX,upY);isDoTouch=false;  //若没有这个,就不会触发onItemClick事件了hasAdd=false;break;case MotionEvent.ACTION_MOVE://System.out.println("ACTION_MOVE");if(this.dragger.isShown()){this.dragger.setVisibility(View.INVISIBLE);}int moveX = (int)ev.getX();int moveY = (int) ev.getY();onDrag(moveX,moveY);break;case MotionEvent.ACTION_DOWN:             //longClick之后不会执行;System.out.println("ACTION_DOWN");int downX = (int)ev.getX();int downY = (int) ev.getY();break;default:break;}return true; }return super.onTouchEvent(ev);}//=======================================================================================================public void onDrag(int x, int y) {if (dragImageView != null) {windowParams.alpha = 0.7f;// 透明度windowParams.x = x - dragPointX + dragOffsetX;windowParams.y = y - dragPointY + dragOffsetY;// 移动y值.//记得要加上dragOffset,windowManager计算的是整个屏幕.(标题栏和状态栏都要算上)windowManager.updateViewLayout(dragImageView, windowParams);// 时时移动.}int tempPosition = pointToPosition(x, y);if (tempPosition != INVALID_POSITION) {dragPosition = tempPosition;}onChange(x,y);// 滚动          if (y < upScrollBounce || y > downScrollBounce) {              // 使用setSelection来实现滚动              setSelection(dragPosition);          }  }public void onChange(int x,int y){if(dragPosition<getAdapter().getCount()){DragGVAdapter adapter = (DragGVAdapter)getAdapter();if(this.tempChangeId!=this.dragPosition){adapter.update(tempChangeId,dragPosition);this.tempChangeId=this.dragPosition;}}int tempPosition=pointToPosition(x,y);if(tempPosition!=INVALID_POSITION){this.dragPosition=tempPosition;}}public void stopDrag() {if (dragImageView != null) {windowManager.removeView(dragImageView);dragImageView = null;}}public void onDrop(int x,int y) {// 数据交换if (dragPosition < getAdapter().getCount()) {DragGVAdapter adapter = (DragGVAdapter)getAdapter();adapter.lastUpdate();}}}

DragGVAdapter.java文件:

package com.smiling.draggridview;import java.util.ArrayList;import android.content.Context;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.ImageView;public class DragGVAdapter extends BaseAdapter{private Context context;private ArrayList<Integer> arrayDrawables;private boolean isHide=false;private int endPosition=-1;public DragGVAdapter(Context c,ArrayList<Integer> pics){this.context=c;this.arrayDrawables=pics;}@Overridepublic int getCount() {// TODO 自动生成的方法存根return this.arrayDrawables.size();}@Overridepublic Object getItem(int arg0) {// TODO 自动生成的方法存根return null;}@Overridepublic long getItemId(int arg0) {// TODO 自动生成的方法存根return arg0;}@Overridepublic View getView(int position, View v, ViewGroup vg) {// TODO 自动生成的方法存根LayoutInflater inflater=LayoutInflater.from(context);v=inflater.inflate(R.layout.drag_gridview_item,null);System.out.println("POSITION="+position);   //连续输出两次POSITION=0;if(position!=endPosition){ImageView imageview=(ImageView)v.findViewById(R.id.drag_gridview_image);imageview.setImageResource(this.arrayDrawables.get(position));imageview.setScaleType(ImageView.ScaleType.FIT_XY);}else if(position==endPosition){ImageView imageview=(ImageView)v.findViewById(R.id.drag_gridview_image);imageview.setImageResource(this.arrayDrawables.get(position));imageview.setScaleType(ImageView.ScaleType.FIT_XY);imageview.setVisibility(View.INVISIBLE);}return v;}public void update(int start, int down) {this.endPosition=down;System.out.println("END="+endPosition);int drawable_id = arrayDrawables.get(start);arrayDrawables.remove(start); arrayDrawables.add(down, drawable_id); notifyDataSetChanged(); }public void lastUpdate(){this.endPosition=-1;notifyDataSetChanged(); }}

这里需要注意几点,首先是方法的执行顺序,是先onInterceptTouchEvent(),然后是onItemLongClick(),接着onTouchEvent(),ACTION_MOVE->ACTION_UP;注意映像应该在onTouchEvent方法中添加,而不能在onInterceptTouchEvent()方法中添加,否则GridView上下滑动也会出现映像。

Sumsang S4实测截图如下:

Android UI - GridView长按实现拖拽效果_第1张图片Android UI - GridView长按实现拖拽效果_第2张图片

更多相关文章

  1. Java如何操作Android的adb shell 之 我自己在程序中的使用方法
  2. Android 改变View位置 setLeft、etRight、setTop、setBottom等在
  3. android:程序中安装APK方法
  4. android图片拖动
  5. 关于android Http访问,上传,用了三个方法
  6. Android的Bitmap类中常用方法
  7. Android 上进行签名的方法
  8. Android jar包Proguard混淆方法
  9. Android中SQLite增删改查的方法(Android开发视频讲座)

随机推荐

  1. android第二天早:简单工具和布局基础
  2. android使用viewpager计算偏移量实现选项
  3. Android一种字幕效果的实现
  4. SearchView使用
  5. Android利用AChartEngine绘制图表
  6. Android(安卓)使用 Android(安卓)Camera
  7. Android(安卓)ListView组件 ArrayAdapter
  8. Android实现一行有好几个TextView 第一个
  9. Android四种常用的消息传递机制/模式的比
  10. 网易云短信android接入