Android中在GridView网格视图上实现item拖拽交换的方法

Android中在GridView网格视图上实现item拖拽交换的方法,第1张

概述GridView基础新建一个HelloGridView的工程修改main.xml代码如下:<?xmlversion=\"1.0\"encoding=\"utf-8\"?>

GrIDVIEw基础
新建一个HelloGrIDVIEw的工程
修改main.xml代码如下:

<?xml version="1.0" enCoding="utf-8"?> <GrIDVIEw  xmlns:androID="http://schemas.androID.com/apk/res/androID"  androID:ID="@+ID/grIDvIEw"  androID:layout_wIDth="fill_parent"  androID:layout_height="fill_parent"  androID:columnWIDth="90dp"  androID:numColumns="auto_fit"  androID:horizontalSpacing="10dp"  androID:verticalSpacing="10dp"  androID:stretchMode="columnWIDth"  androID:gravity="center"> </GrIDVIEw> 

 很简单,就是一个GrIDVIEw。设置列宽为90dp,这样当我们的numColumns设置为auto_fit时,AndroID就会自动计算我们手机屏幕的大小以决定每一行展示几个元素。这是很方便。androID:horizontalSpacing定义列之间的间隔,androID:verticalSpacing定义行之间的间隔。androID:stretchMode设置为columnWIDth是意味着根据列宽自动缩放。
修改我们Activity HelloGrIDVIEw如下:

public class HelloGrIDVIEw extends Activity {   /** Called when the activity is first created. */   @OverrIDe   protected voID onCreate(Bundle savedInstanceState) {     super.onCreate(savedInstanceState);     setContentVIEw(R.layout.main);     GrIDVIEw grIDVIEw=(GrIDVIEw)findVIEwByID(R.ID.grIDvIEw);     grIDVIEw.setAdapter(new ImageAdapter(this));     //单击GrIDVIEw元素的响应     grIDVIEw.setonItemClickListener(new OnItemClickListener() {        @OverrIDe       public voID onItemClick(AdapterVIEw<?> parent,VIEw vIEw,int position,long ID) {         //d出单击的GrIDVIEw元素的位置         Toast.makeText(HelloGrIDVIEw.this,mThumbIDs[position],Toast.LENGTH_SHORT).show();       }     });   }   private class ImageAdapter extends BaseAdapter{     private Context mContext;      public ImageAdapter(Context context) {       this.mContext=context;     }      @OverrIDe     public int getCount() {       return mThumbIDs.length;     }      @OverrIDe     public Object getItem(int position) {       return mThumbIDs[position];     }      @OverrIDe     public long getItemID(int position) {       // Todo auto-generated method stub       return 0;     }      @OverrIDe     public VIEw getVIEw(int position,VIEw convertVIEw,VIEwGroup parent) {       //定义一个ImageVIEw,显示在GrIDVIEw里       ImageVIEw imageVIEw;       if(convertVIEw==null){         imageVIEw=new ImageVIEw(mContext);         imageVIEw.setLayoutParams(new GrIDVIEw.LayoutParams(85,85));         imageVIEw.setScaleType(ImageVIEw.ScaleType.CENTER_CROP);         imageVIEw.setpadding(8,8,8);       }else{         imageVIEw = (ImageVIEw) convertVIEw;       }       imageVIEw.setimageResource(mThumbIDs[position]);       return imageVIEw;     }              }   //展示图片   private Integer[] mThumbIDs = {       R.drawable.sample_2,R.drawable.sample_3,R.drawable.sample_4,R.drawable.sample_5,R.drawable.sample_6,R.drawable.sample_7,R.drawable.sample_0,R.drawable.sample_1,R.drawable.sample_2,R.drawable.sample_7   }; } 

 这里我们也是采用的自定义Adapter,可以上一节的自定义Adapter讲解。展示了一些图片,然后点击一个图片的时候会显示这个图片所在的位置。
运行程序,效果图如下:

长按可拖拽和item实时交换
GrIDVIEw主要是来显示网格的控件,在AndroID的开发中使用很普通,相对于TextVIEw,button这些控件来说要来的复杂些,今天给大家带来长按GrIDVIEw的item,然后将其拖拽其他item上面,使得GrIDVIEw的item发生交换,比较典型的就是我们的Launcher,网上有很多关于GrIDVIEw的拖动的Demo,但是大部分都是相同的,而且存在一些BUG,而且大部分都是点击GrIDVIEw的item然后进行拖动,或者item之间不进行实时交换,今天给大家更加详细的介绍GrIDVIEw拖拽,并且将Demo做的更完美,大家更容易接受,也许很多人听到这个感觉实现起来很复杂,就关掉的这篇文章,其实告诉大家,只要知道了思路就感觉一点都不复杂了,不信大家可以接着往下看看,首先还是跟大家说说实现的思路
根据手指按下的X,Y坐标来获取我们在GrIDVIEw上面点击的item
手指按下的时候使用Handler和Runnable来实现一个定时器,假如定时时间为1000毫秒,在1000毫秒内,如果手指抬起了移除定时器,没有抬起并且手指点击在GrIDVIEw的item所在的区域,则表示我们长按了GrIDVIEw的item
如果我们长按了item则隐藏item,然后使用WindowManager来添加一个item的镜像在屏幕用来代替刚刚隐藏的item
当我们手指在屏幕移动的时候,更新item镜像的位置,然后在根据我们移动的X,Y的坐标来获取移动到GrIDVIEw的哪一个位置
到GrIDVIEw的item过多的时候,可能一屏幕显示不完,我们手指拖动item镜像到屏幕下方,要触发GrIDVIEw想上滚动,同理,当我们手指拖动item镜像到屏幕上面,触发GrIDVIEw向下滚动
GrIDVIEw交换数据,刷新界面,移除item的镜像
看完上面的这些思路你是不是找到了些感觉了呢,心里痒痒的想动手试试吧,好吧,接下来就带大家根据思路来实现可拖拽的GrIDVIEw,新建一个项目就叫DragGrIDVIEw
新建一个类DragGrIDVIEw继承GrIDVIEw,先来看看DragGrIDVIEw的代码,然后在根据代码进行相关的讲解

package com.example.draggrIDvIEw;  import androID.app.Activity; import androID.content.Context; import androID.graphics.Bitmap; import androID.graphics.PixelFormat; import androID.graphics.Rect; import androID.os.Handler; import androID.os.Vibrator; import androID.util.AttributeSet; import androID.vIEw.Gravity; import androID.vIEw.MotionEvent; import androID.vIEw.VIEw; import androID.vIEw.WindowManager; import androID.Widget.AdapterVIEw; import androID.Widget.GrIDVIEw; import androID.Widget.ImageVIEw;  public class DragGrIDVIEw extends GrIDVIEw{   /**    * DragGrIDVIEw的item长按响应的时间, 默认是1000毫秒,也可以自行设置    */   private long dragResponseMS = 1000;      /**    * 是否可以拖拽,默认不可以    */   private boolean isDrag = false;      private int mDownX;   private int mDownY;   private int moveX;   private int moveY;   /**    * 正在拖拽的position    */   private int mDragposition;      /**    * 刚开始拖拽的item对应的VIEw    */   private VIEw mStartDragItemVIEw = null;      /**    * 用于拖拽的镜像,这里直接用一个ImageVIEw    */   private ImageVIEw mDragImageVIEw;      /**    * 震动器    */   private Vibrator mVibrator;      private WindowManager mWindowManager;   /**    * item镜像的布局参数    */   private WindowManager.LayoutParams mWindowLayoutParams;      /**    * 我们拖拽的item对应的Bitmap    */   private Bitmap mDragBitmap;      /**    * 按下的点到所在item的上边缘的距离    */   private int mPoint2Itemtop ;       /**    * 按下的点到所在item的左边缘的距离    */   private int mPoint2Itemleft;      /**    * DragGrIDVIEw距离屏幕顶部的偏移量    */   private int mOffset2top;      /**    * DragGrIDVIEw距离屏幕左边的偏移量    */   private int mOffset2left;      /**    * 状态栏的高度    */   private int mStatusHeight;       /**    * DragGrIDVIEw自动向下滚动的边界值    */   private int mDownScrollborder;      /**    * DragGrIDVIEw自动向上滚动的边界值    */   private int mUpScrollborder;      /**    * DragGrIDVIEw自动滚动的速度    */   private static final int speed = 20;      /**    * item发生变化回调的接口    */   private OnChanageListener onChanageListener;            public DragGrIDVIEw(Context context) {     this(context,null);   }      public DragGrIDVIEw(Context context,AttributeSet attrs) {     this(context,attrs,0);   }    public DragGrIDVIEw(Context context,AttributeSet attrs,int defStyle) {     super(context,defStyle);     mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);     mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);     mStatusHeight = getStatusHeight(context); //获取状态栏的高度        }      private Handler mHandler = new Handler();      //用来处理是否为长按的Runnable   private Runnable mLongClickRunnable = new Runnable() {          @OverrIDe     public voID run() {       isDrag = true; //设置可以拖拽       mVibrator.vibrate(50); //震动一下       mStartDragItemVIEw.setVisibility(VIEw.INVISIBLE);//隐藏该item              //根据我们按下的点显示item镜像       createDragImage(mDragBitmap,mDownX,mDownY);     }   }; 

      

  /**    * 设置回调接口    * @param onChanageListener    */   public voID setonchangelistener(OnChanageListener onChanageListener){     this.onChanageListener = onChanageListener;   }      /**    * 设置响应拖拽的毫秒数,默认是1000毫秒    * @param dragResponseMS    */   public voID setDragResponseMS(long dragResponseMS) {     this.dragResponseMS = dragResponseMS;   }    @OverrIDe   public boolean dispatchtouchEvent(MotionEvent ev) {     switch(ev.getAction()){     case MotionEvent.ACTION_DOWN:       mDownX = (int) ev.getX();       mDownY = (int) ev.getY();              //根据按下的X,Y坐标获取所点击item的position       mDragposition = pointToposition(mDownX,mDownY);                     if(mDragposition == AdapterVIEw.INVALID_position){         return super.dispatchtouchEvent(ev);       }              //使用Handler延迟dragResponseMS执行mLongClickRunnable       mHandler.postDelayed(mLongClickRunnable,dragResponseMS);              //根据position获取该item所对应的VIEw       mStartDragItemVIEw = getChildAt(mDragposition - getFirstVisibleposition());              //下面这几个距离大家可以参考我的博客上面的图来理解下       mPoint2Itemtop = mDownY - mStartDragItemVIEw.gettop();       mPoint2Itemleft = mDownX - mStartDragItemVIEw.getleft();              mOffset2top = (int) (ev.getRawY() - mDownY);       mOffset2left = (int) (ev.getRawX() - mDownX);              //获取DragGrIDVIEw自动向上滚动的偏移量,小于这个值,DragGrIDVIEw向下滚动       mDownScrollborder = getHeight() /4;       //获取DragGrIDVIEw自动向下滚动的偏移量,大于这个值,DragGrIDVIEw向上滚动       mUpScrollborder = getHeight() * 3/4;                            //开启mDragItemVIEw绘图缓存       mStartDragItemVIEw.setDrawingCacheEnabled(true);       //获取mDragItemVIEw在缓存中的Bitmap对象       mDragBitmap = Bitmap.createBitmap(mStartDragItemVIEw.getDrawingCache());       //这一步很关键,释放绘图缓存,避免出现重复的镜像       mStartDragItemVIEw.destroyDrawingCache();                     break;     case MotionEvent.ACTION_MOVE:       int moveX = (int)ev.getX();       int moveY = (int) ev.getY();              //如果我们在按下的item上面移动,只要不超过item的边界我们就不移除mRunnable       if(!istouchInItem(mStartDragItemVIEw,moveX,moveY)){         mHandler.removeCallbacks(mLongClickRunnable);       }       break;     case MotionEvent.ACTION_UP:       mHandler.removeCallbacks(mLongClickRunnable);       mHandler.removeCallbacks(mScrollRunnable);       break;     }     return super.dispatchtouchEvent(ev);   } 

  
      

  /**    * 是否点击在GrIDVIEw的item上面    * @param itemVIEw    * @param x    * @param y    * @return    */   private boolean istouchInItem(VIEw dragVIEw,int x,int y){     if(dragVIEw == null){       return false;     }     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;   }          @OverrIDe   public boolean ontouchEvent(MotionEvent ev) {     if(isDrag && mDragImageVIEw != null){       switch(ev.getAction()){       case MotionEvent.ACTION_MOVE:         moveX = (int) ev.getX();         moveY = (int) ev.getY();         //拖动item         onDragItem(moveX,moveY);         break;       case MotionEvent.ACTION_UP:         onStopDrag();         isDrag = false;         break;       }       return true;     }     return super.ontouchEvent(ev);   } 

      
      

  /**    * 创建拖动的镜像    * @param bitmap    * @param downX    *     按下的点相对父控件的X坐标    * @param downY    *     按下的点相对父控件的X坐标    */   private voID createDragImage(Bitmap bitmap,int downX,int downY){     mWindowLayoutParams = new WindowManager.LayoutParams();     mWindowLayoutParams.format = PixelFormat.TRANSLUCENT; //图片之外的其他地方透明     mWindowLayoutParams.gravity = Gravity.top | Gravity.left;     mWindowLayoutParams.x = downX - mPoint2Itemleft + mOffset2left;     mWindowLayoutParams.y = downY - mPoint2Itemtop + mOffset2top - mStatusHeight;     mWindowLayoutParams.Alpha = 0.55f; //透明度     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 removeDragImage(){     if(mDragImageVIEw != null){       mWindowManager.removeVIEw(mDragImageVIEw);       mDragImageVIEw = null;     }   } 

      

  /**    * 拖动item,在里面实现了item镜像的位置更新,item的相互交换以及GrIDVIEw的自行滚动    * @param x    * @param y    */   private voID onDragItem(int moveX,int moveY){     mWindowLayoutParams.x = moveX - mPoint2Itemleft + mOffset2left;     mWindowLayoutParams.y = moveY - mPoint2Itemtop + mOffset2top - mStatusHeight;     mWindowManager.updateVIEwLayout(mDragImageVIEw,mWindowLayoutParams); //更新镜像的位置     onSwAPItem(moveX,moveY);          //GrIDVIEw自动滚动     mHandler.post(mScrollRunnable);   } 
      
  /**    * 当moveY的值大于向上滚动的边界值,触发GrIDVIEw自动向上滚动    * 当moveY的值小于向下滚动的边界值,触犯GrIDVIEw自动向下滚动    * 否则不进行滚动    */   private Runnable mScrollRunnable = new Runnable() {          @OverrIDe     public voID run() {       int scrollY;       if(moveY > mUpScrollborder){          scrollY = speed;          mHandler.postDelayed(mScrollRunnable,25);       }else if(moveY < mDownScrollborder){         scrollY = -speed;          mHandler.postDelayed(mScrollRunnable,25);       }else{         scrollY = 0;         mHandler.removeCallbacks(mScrollRunnable);       }              //当我们的手指到达GrIDVIEw向上或者向下滚动的偏移量的时候,可能我们手指没有移动,但是DragGrIDVIEw在自动的滚动       //所以我们在这里调用下onSwAPItem()方法来交换item       onSwAPItem(moveX,moveY);                     smoothScrollBy(scrollY,10);     }   }; 
      
  /**    * 交换item,并且控制item之间的显示与隐藏效果    * @param moveX    * @param moveY    */   private voID onSwAPItem(int moveX,int moveY){     //获取我们手指移动到的那个item的position     int tempposition = pointToposition(moveX,moveY);          //假如tempposition 改变了并且tempposition不等于-1,则进行交换     if(tempposition != mDragposition && tempposition != AdapterVIEw.INVALID_position){       if(onChanageListener != null){         onChanageListener.onChange(mDragposition,tempposition);       }              getChildAt(tempposition - getFirstVisibleposition()).setVisibility(VIEw.INVISIBLE);//拖动到了新的item,新的item隐藏掉       getChildAt(mDragposition - getFirstVisibleposition()).setVisibility(VIEw.VISIBLE);//之前的item显示出来              mDragposition = tempposition;     }   } 
      
     /**    * 停止拖拽我们将之前隐藏的item显示出来,并将镜像移除    */   private voID onStopDrag(){     VIEw vIEw = getChildAt(mDragposition - getFirstVisibleposition());     if(vIEw != null){       vIEw.setVisibility(VIEw.VISIBLE);     }     ((DragAdapter)this.getAdapter()).setItemHIDe(-1);     removeDragImage();   } 
      
  /**    * 获取状态栏的高度    * @param context    * @return    */   private static 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;   } 
 
  /**    *    * @author xiaanming    *    */   public interface OnChanageListener{          /**      * 当item交换位置的时候回调的方法,我们只需要在该方法中实现数据的交换即可      * @param form      *     开始的position      * @param to      *     拖拽到的position      */     public voID onChange(int form,int to);   } } 

首先看DragGrIDVIEw的事件分发方法,不了解AndroID事件分发的可以先去了解下,AndroID事件分发对于自定义控件很重要,简单说下,当我们点击DragGrIDVIEw的Item,先会去执行dispatchtouchEvent()方法将事件分发下去,所以我们要重写dispatchtouchEvent()方法在手指按下的时候根据pointToposition()方法来获取我们按下的item的position,根据getChildAt()方法来获取该position上面所对应的VIEw,并且开启长按的定时器,默认时间为1000毫秒,如果在1000毫秒内手指抬起或者手指在屏幕上滑动出了该item,则取消长按定时器,否则就表示可以进行拖拽,手机友好的震动一下,隐藏我们长按的Item,屏幕调用createDragImage()方法来创建我们长按的item的镜像,创建Item的镜像使用的是WindowManager类,该类可以创建一个窗体显示在Activity之上,
再此之前大家先要理解这几个距离,理解这几个距离之前要首先知道getRawX(),getRawY()和getX(),getY()的区别,getRawX(),getRawY()是相对于屏幕的原点的距离,而getX(),getY()是相对于控件左上方的点的距离,为了方便大家理解我用Word简单的画了下图,画得不好,大家将就的看下,红色框框为我们的GrIDVIEw

@H_419_112@mPoint2Itemtop 手指按下的点到该Item的上边缘的距离,如上图的1号线 @H_419_112@mPoint2Itemleft 手指按下的点到该Item的左边缘的距离,如上图的2号线 @H_419_112@mOffset2top  DragGrIDVIEw的上边缘到屏幕上边缘的距离,如上图的3号线,这个距离包裹状态栏,标题栏,或者一些在DragGrIDVIEw上面的布局的高度,这个很重要我们现实Item镜像需要用到 @H_419_112@mOffset2left DragGrIDVIEw的左边缘到屏幕左边缘的距离,如上图的4号线,我这个Demo的这个距离为0,因为我设置DragGrIDVIEw的宽度为充满屏幕,但是我们要考虑假如DragGrIDVIEw与屏幕左边缘设置了间隙或者左边有其他的布局的情形 @H_419_112@mDownScrollborder 这个距离表示当DragGrIDVIEw的item过多的时候,手机一屏显示不完全,我们拖动Item镜像到这个高度的时候,DragGrIDVIEw自动向下滚动,如上图的5号线 @H_419_112@.mUpScrollborder 这个和mDownScrollborder相反,当我们大于这个高度的时候,DragGrIDVIEw自动向上滚动,如上图的6号线

理解了这六个距离,我们就来看看创建Item镜像的方法里面,其他的我不多说,首先设置format为PixelFormat.TRANSLUCENT,表示除了我们显示图片和文字的其他地方为透明,之后就是x,y这两个距离的计算,计算的是item的左上角的坐标,理解了上面这六个距离我们很容易得出x,y的坐标,可是你会发现y的坐标减去了状态栏的高度,这点大家需要注意下,另外我们需要获取item的绘制缓存的Bitmap对象,然后将Bitmap设置到一个ImageVIEw上面,为什么要这么做呢?如果调用addVIEw()方法将item 直接添加到WindowManager里面,会有异常产生,因为item已经有了自己归属的父容器DragGrIDVIEw,所有我们这里使用一个ImageVIEw来代替item添加到WindowManager里面

上面已经完成了开始拖拽的准备工作,要想拖动镜像我们还需要重写ontouchEvent()方法,获取移动的X,Y的坐标,利用WindowManager的updateVIEwLayout方法就能对镜像进行拖动,拖动的镜像的时候为了有更好的用户体验,我们还要做item的实时交换效果,我们利用手指移动的X,Y坐标,利用pointToposition()来获取拖拽到的position,然后将之前的item显示出来,将拖拽到的item进行隐藏,这样子就完成了item在界面上面的交换,但是数据交换我这里没有做,所以我提供了回调接口OnChanageListener,我们只需要自己实现数据的交换逻辑然后刷新DragGrIDVIEw即可,我们还需要实现DragGrIDVIEw的自动向上滚动或者向下滚动,使用Handler和mScrollRunnable利用smoothScrollTopositionFromtop()来实现DragGrIDVIEw滚动,具体的实现大家可以看代码
手指离开界面,将item的镜像移除,并将拖拽到的item显示出来,这样子就实现了GirdVIEw的拖拽效果啦,接下来我们来使用下我们自定义可拖拽的GrIDVIEw吧,先看主界面布局,只有我们自定义的一个DragGrIDVIEw

<relativeLayout xmlns:androID="http://schemas.androID.com/apk/res/androID"   xmlns:tools="http://schemas.androID.com/tools"   androID:layout_wIDth="match_parent"   androID:layout_height="match_parent" >    <com.example.draggrIDvIEw.DragGrIDVIEw     androID:ID="@+ID/dragGrIDVIEw"     androID:ListSelector="@androID:color/transparent"     androID:layout_wIDth="match_parent"     androID:layout_height="match_parent"     androID:cachecolorHint="@androID:color/transparent"     androID:verticalSpacing="10dip"     androID:horizontalSpacing="10dip"     androID:stretchMode="columnWIDth"      androID:gravity="center"      androID:numColumns="3" >   </com.example.draggrIDvIEw.DragGrIDVIEw>  </relativeLayout> 

接下来我们看看DragGrIDVIEw的item的布局,上面一个ImageVIEw下面一个TextVIEw

<?xml version="1.0" enCoding="utf-8"?> <relativeLayout xmlns:androID="http://schemas.androID.com/apk/res/androID"   androID:layout_wIDth="fill_parent"   androID:layout_height="wrap_content"   androID:background="@androID:color/transparent" >    <ImageVIEw     androID:ID="@+ID/item_image"     androID:scaleType="centerCrop"     androID:layout_wIDth="wrap_content"     androID:layout_height="wrap_content"     androID:layout_centerHorizontal="true" >   </ImageVIEw>    <TextVIEw     androID:ID="@+ID/item_text"     androID:layout_wIDth="wrap_content"     androID:layout_height="wrap_content"     androID:layout_below="@+ID/item_image"     androID:layout_centerHorizontal="true" >   </TextVIEw>  </relativeLayout> 

布局搞定了我们就来看看主页面MainActivity的代码吧

package com.example.draggrIDvIEw;  import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List;  import androID.app.Activity; import androID.os.Bundle; import androID.Widget.SimpleAdapter;  import com.example.draggrIDvIEw.DragGrIDVIEw.OnChanageListener; public class MainActivity extends Activity {   private List<HashMap<String,Object>> dataSourceList = new ArrayList<HashMap<String,Object>>();    @OverrIDe   protected voID onCreate(Bundle savedInstanceState) {     super.onCreate(savedInstanceState);     setContentVIEw(R.layout.activity_main);      DragGrIDVIEw mDragGrIDVIEw = (DragGrIDVIEw) findVIEwByID(R.ID.dragGrIDVIEw);     for (int i = 0; i < 30; i++) {       HashMap<String,Object> itemHashMap = new HashMap<String,Object>();       itemHashMap.put("item_image",R.drawable.com_tencent_open_notice_msg_icon_big);       itemHashMap.put("item_text","拖拽 " + Integer.toString(i));       dataSourceList.add(itemHashMap);     }           final SimpleAdapter mSimpleAdapter = new SimpleAdapter(this,dataSourceList,R.layout.grID_item,new String[] { "item_image","item_text" },new int[] { R.ID.item_image,R.ID.item_text });          mDragGrIDVIEw.setAdapter(mSimpleAdapter);          mDragGrIDVIEw.setonchangelistener(new OnChanageListener() {              @OverrIDe       public voID onChange(int from,int to) {         HashMap<String,Object> temp = dataSourceList.get(from);         //直接交互item //       dataSourceList.set(from,dataSourceList.get(to)); //       dataSourceList.set(to,temp); //       dataSourceList.set(to,temp);                           //这里的处理需要注意下         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();                         }     });        }  } 

这里面的代码还是比较简单,主要讲下onChange()方法,我们要为mDragGrIDVIEw设置一个OnChanageListener的回调接口,在onChange()方法里面实现数据的交换逻辑,第一个参数from为item开始的位置,第二个参数to为item拖拽到的位置,刚开始我使用的交换逻辑是

HashMap<String,temp); 

直接交换的item的数据,然后看了下网易新闻的拖拽的GrIDVIEw,他不是直接实现两个item直接的数据交换,所以将数据交换逻辑改成了下面的方式
简单说下,数据的交换逻辑,比如我们将position从5拖拽到7这个位置,我注释掉的逻辑是直接将5和7的数据交换,而后面的那种逻辑是将6的位置数据移动到5,将7的位置移动到6,然后再7显示5  6->5,7->6,5->7不知道大家理解了没有。
接下来我们来运行下项目,在运行之前我们不要忘了在AndroIDManifest.xml里面加入震动的权限<uses-permission androID:name="androID.permission.VIBRATE"/>

好了,今天的讲解就到此结束,效果还不错吧,看完这篇文章你是不是觉得GrIDVIEw拖拽也不是那么难实现呢?你心里是不是也大概有自己的一个思路,建议大家自己敲敲看看,可以自己去实现下ListVIEw的拖拽实现,ListVIEw比GrIDVIEw简单些。

总结

以上是内存溢出为你收集整理的Android中在GridView网格视图上实现item拖拽交换的方法全部内容,希望文章能够帮你解决Android中在GridView网格视图上实现item拖拽交换的方法所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/1149474.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-31
下一篇2022-05-31

发表评论

登录后才能评论

评论列表(0条)

    保存