大佬教程收集整理的这篇文章主要介绍了Android自定义View实现可以拖拽的GridView,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
先看看效果图
@H_675_5@
主要思想:
1、监听触碰事件
2、用WindowManager添加拖曳的图片
3、用Collections.swap()交换List数据
public class DragGridVeiw extends GridView { private final int PRESS_TIME = 1000;//长按时间 privatE int mDownX;//触碰时的X坐标 privatE int mDownY;//触碰时的Y坐标 privatE int mMoveX;//移动时的X坐标 privatE int mMoveY;//移动时的Y坐标 privatE int mOffset2Top;//DragGridView距离屏幕顶部的偏移量 privatE int mOffset2Left;//DragGridView距离屏幕左边的偏移量 privatE int mPointToItemTop;//触碰点距离ItemView的上边距 privatE int mPointToItemLeft;//触碰点距离ItemView的左边距 privatE int mStatusHeight;//状态栏高度 private Boolean isDraging;//是否正在拖曳 private Bitmap mBitmap;//ItemView的图片 privatE int mTouchPostiion;//触碰的位置 private View mTouchItemView;//触碰的ItemView private Vibrator mVibrator;//震动器 private ImageView mDragImageView;//拖曳的View private WindowManager mWindowManager;//窗口管理器 private WindowManager.LayoutParams mWindowLayoutParams;//窗口管理器布局 private OnChanageListener onChanageListener;//交换事件监听器 private Handler mHandler = new Handler(); public DragGridVeiw(Context context) { this(context,null); } public DragGridVeiw(Context context,AttributeSet attrs) { this(context,attrs,0); } public DragGridVeiw(Context context,AttributeSet attrs,int defStyleAttr) { super(context,defStyleAttr); mStatusHeight = getStatusHeight(context); mVibrator = (Vibrator) context.getSystemservice(Context.VIBRATOR_serviCE); mWindowManager = (WindowManager) context.getSystemservice(Context.WINDOW_serviCE); } @Override public Boolean dispatchTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: //使用Handler延迟dragResponseMS执行mLongClickRunnable mHandler.postDelayed(mLongClickRunnable,PRESS_TIME); mDownX = (int) ev.getX(); mDownY = (int) ev.getY(); //根据按下的X,Y坐标获取所点击item的position mTouchPostiion = pointToPosition(mDownX,mDownY); if (mTouchPostiion == AdapterView.INVALID_POSITION) { return super.dispatchTouchEvent(ev); } //根据position获取该item所对应的View mTouchItemView = getChildAt(mTouchPostiion - getFirstVisiblePosition()); //下面这几个距离大家可以参考我的博客上面的图来理解下 mPointToItemTop = mDownY - mTouchItemView.getTop(); mPointToItemLeft = mDownX - mTouchItemView.getLeft(); mOffset2Top = (int) (ev.getRawY() - mDownY); mOffset2Left = (int) (ev.getRawX() - mDownX); //开启mDragItemView绘图缓存 mTouchItemView.setDrawingCacheEnabled(true); //@L_159_8@mDragItemView在缓存中的Bitmap对象 mBitmap = Bitmap.createBitmap(mTouchItemView.getDrawingCache()); //这一步很关键,释放绘图缓存,避免出现重复的镜像 mTouchItemView.destroyDrawingCache(); break; case MotionEvent.ACTION_MOVE: int moveX = (int) ev.getX(); int moveY = (int) ev.getY(); //拖曳点超出GridView区域则取消拖曳事件 if (ev.getY() > getHeight() || ev.getY() < 0) { onStopDrag(); } //如果我们在按下的item上面移动,只要超过item的边界就移除mRunnable if (!isTouchInItem(mTouchItemView,moveX,moveY)) { mHandler.removeCallBACks(mLongClickRunnablE); } break; case MotionEvent.ACTION_UP: mHandler.removeCallBACks(mLongClickRunnablE); break; } return super.dispatchTouchEvent(ev); } @Override public Boolean onTouchEvent(MotionEvent ev) { if (isDraging && mDragImageView != null) { switch (ev.getAction()) { case MotionEvent.ACTION_MOVE: mMoveX = (int) ev.getX(); mMoveY = (int) ev.getY(); //拖动item onDragItem(mMoveX,mMoveY); break; case MotionEvent.ACTION_UP: onStopDrag(); break; } return true; } return super.onTouchEvent(ev); } //处理长按事件的线程 private Runnable mLongClickRunnable = new Runnable() { @Override public void run() { isDraging = true; //设置可以拖拽 mVibrator.vibrate(50); //震动一下 mTouchItemView.setVisibility(View.INVISIBLE);//隐藏该ItemView //根据我们按下的点显示ItemView镜像 createDragView(mBitmap,mDownX,mDownY); } }; //添加拖动View private void createDragView(Bitmap bitmap,int downX,int downY) { mWindowLayoutParams = new WindowManager.LayoutParams(); mWindowLayoutParams.format = PixelFormat.TRANSLUCENT; //图片之外的其他地方透明 mWindowLayoutParams.gravity = Gravity.TOP | Gravity.LEFT; mWindowLayoutParams.x = downX - mPointToItemTop + mOffset2Left; mWindowLayoutParams.y = downY - mPointToItemTop + mOffset2Top - mStatusHeight; mWindowLayoutParams.alpha = 0.6f; //透明度 mWindowLayoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT; mWindowLayoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT; mWindowLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; mDragImageView = new ImageView(getContext()); mDragImageView.setImageBitmap(bitmap); mWindowManager.addView(mDragImageView,mWindowLayoutParams); } private void removeDragView() { if (mDragImageView != null) { mWindowManager.removeView(mDragImageView); mDragImageView = null; } } //是否点击在GridView的item上面 private Boolean isTouchInItem(View dragView,int x,int y) { int leftOffset = dragView.getLeft(); int topOffset = dragView.getTop(); if (x < leftOffset || x > leftOffset + dragView.getWidth()) { return false; } if (y < topOffset || y > topOffset + dragView.getHeight()) { return false; } return true; } //拖动事件处理 private void onDragItem(int moveX,int moveY) { mWindowLayoutParams.x = moveX - mPointToItemLeft + mOffset2Left; mWindowLayoutParams.y = moveY - mPointToItemTop + mOffset2Top - mStatusHeight; mWindowManager.updateViewLayout(mDragImageView,mWindowLayoutParams); //更新DragView的位置 onSwapItem(moveX,moveY);//Item的相互交换 } //交换item,并且控制item之间的显示与隐藏效果 private void onSwapItem(int moveX,int moveY) { //获取我们手指移动到的那个item的position int tempPosition = pointToPosition(moveX,moveY); //假如tempPosition 改变了并且tempPosition不等于-1,则进行交换 if (tempPosition != mTouchPostiion && tempPosition != AdapterView.INVALID_POSITION) { getChildAt(tempPosition - getFirstVisiblePosition()).setVisibility(View.INVISIBLE);//拖动到了新的item,新的item隐藏掉 getChildAt(mTouchPostiion - getFirstVisiblePosition()).setVisibility(View.VISIBLE);//之前的item显示出来 if (onChanageListener != null) { onChanagelistener.onChange(mTouchPostiion,tempPosition); } mTouchPostiion = tempPosition; } } //停止拖拽我们将之前隐藏的item显示出来,并将DragView移除 private void onStopDrag() { isDraging = false; getChildAt(mTouchPostiion - getFirstVisiblePosition()).setVisibility(View.VISIBLE); removeDragView(); } //Item交换事件监听 public void setOnchangelistener(OnChanageListener onChanageListener) { this.onChanageListener = onChanageListener; } //获取状态栏高度 privatE int getStatusHeight(Context context) { int statusHeight = 0; Rect localRect = new Rect(); ((Activity) context).getWindow().getDecorView().getWindowVisibleDisplayFrame(localRect); statusHeight = localRect.top; if (0 == statusHeight) { Class<?> localClass; try { localClass = Class.forName("com.android.internal.R$dimen"); Object localObject = localClass.newInstance(); int i5 = Integer.parseInt(localClass.getField("status_bar_height").get(localObject).toString()); statusHeight = context.getresources().getDimensionPixelSize(i5); } catch (Exception E) { e.printStackTrace(); } } return statusHeight; } //当item交换位置的时候回调的方法,我们只需要在该方法中实现数据的交换即可 public interface OnChanageListener { public void onChange(int from,int to); } }
使用方法:
List<HashMap<String,Object>> datasourceList = new ArrayList<>(); dragVeiw = (DragGridVeiw) findViewById(R.id.view_drag); for (int i = 0; i < 8; i++) { HashMap<String,Object> itemHashMap = new HashMap<>(); itemHashMap.put("item_image",R.drawable.sample_1); itemHashMap.put("item_text","拖拽 " + Integer.toString(i)); datasourceList.add(itemHashMap); } final SimpleAdapter mSimpleAdapter = new SimpleAdapter(this,datasourceList,R.layout.item_drag,new String[]{"item_image","item_text"},new int[]{R.id.item_image,R.id.item_text}); dragVeiw.setAdapter(mSimpleAdapter); dragVeiw.setOnchangelistener(new DragGridVeiw.onChanageListener() { @Override public void onChange(int from,int to) { HashMap<String,Object> temp = datasourceList.get(from); //这里的处理需要注意下 if (from < to) { for (int i = from; i < to; i++) { Collections.swap(datasourceList,i,i + 1); } } else if (from > to) { for (int i = from; i > to; i--) { Collections.swap(datasourceList,i - 1); } } datasourceList.set(to,temp); mSimpleAdapter.notifyDataSetChanged(); } });
附录:
Log.v("-->getWidth",String.valueOf(getWidth()));//DragView的宽度 Log.v("-->getHeight",String.valueOf(getHeight()));//DragView的高度 Log.v("-->getLeft",String.valueOf(getLeft()));//DragView左边距离屏幕左侧的长度 Log.v("-->getTop",String.valueOf(getTop()));///DragView上边距离屏幕顶部的长度 Log.v("-->getRawX",String.valueOf(ev.getRawX()));//触碰点相对于屏幕的X坐标 Log.v("-->getRawY",String.valueOf(ev.getRawY()));//触碰点相对于屏幕的Y坐标 Log.v("-->getX",String.valueOf(ev.getX()));//触碰点相对于DragView的X坐标 Log.v("-->getY",String.valueOf(ev.getY()));//触碰点相对于DragView的Y坐标 Log.v("-->getItemWidth",String.valueOf(mTouchItemView.getWidth()));//DragView中ItemView的宽度 Log.v("-->getItemHeight",String.valueOf(mTouchItemView.getHeight()));//DragView中ItemView的高度 Log.v("-->getItemLeft",String.valueOf(mTouchItemView.getLeft()));//DragView中ItemView左边距离DragView左侧的长度 Log.v("-->getItemTop",String.valueOf(mTouchItemView.getTop()));//DragView中ItemView上边距离DragView顶部的长度
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程小技巧。
以上是大佬教程为你收集整理的Android自定义View实现可以拖拽的GridView全部内容,希望文章能够帮你解决Android自定义View实现可以拖拽的GridView所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。