Android UI - GridView长按实现拖拽效果

本文介绍如何在Android中使用GridView控件实现长按拖拽功能,包括自定义控件DragGridViewEx的实现步骤及关键代码解析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >



http://blog.youkuaiyun.com/ialienworld/article/details/11607009

http://blog.youkuaiyun.com/ialienworld/article/details/11607009

http://blog.youkuaiyun.com/ialienworld/article/details/11607009

http://blog.youkuaiyun.com/ialienworld/article/details/11607009

http://blog.youkuaiyun.com/ialienworld/article/details/11607009

http://blog.youkuaiyun.com/ialienworld/article/details/11607009





对于没有及时发送代码的网友说声SORRY,下载链接如下
http://download.youkuaiyun.com/detail/u010129564/6892329


 

Android UI - GridView长按实现拖拽效果

分类: ANDROID UI DESIGN   689人阅读  评论(12)  收藏  举报
[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. DragGridViewEx.java文件:  
[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1.   
[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. package com.smiling.draggridview;  
  2.   
  3. /* 
  4.  * onInterceptTouchEvent() -> onItemLongClick() -> onTouchEvent()->ACTION_MOVE->ACTION_UP; 
  5.  *  
  6.  * */  
  7. import android.content.Context;  
  8. import android.graphics.Bitmap;  
  9. import android.graphics.Color;  
  10. import android.util.AttributeSet;  
  11. import android.view.Gravity;  
  12. import android.view.MotionEvent;  
  13. import android.view.View;  
  14. import android.view.ViewGroup;  
  15. import android.view.WindowManager;  
  16. import android.widget.AdapterView;  
  17. import android.widget.GridView;  
  18. import android.widget.ImageView;  
[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1.   
[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. //以下为自定义GridView控件;  
  2.   
  3. public class DragGridViewEx extends GridView{  
  4.   
  5.     private WindowManager windowManager;// windows窗口控制类  
  6.     private WindowManager.LayoutParams windowParams;// 用于控制拖拽项的显示的参数      
  7.     private ImageView dragImageView;// 被拖拽的项(item),其实就是一个ImageView\  
  8.       
  9.     private View  itemView=null;  
  10.     private Bitmap bm;  
  11.     private ImageView imageView;  
  12.     private View dragger;  
  13.     private int dragSrcPosition;// 手指拖动项在列表中的原始位置  
  14.     private int dragPosition;// 手指点击准备拖动的时候,当前拖动项在列表中的位置.  
  15.     private int dragPointX;  
  16.     private int dragPointY;// 在当前数据项中的位置  
  17.     private int dragOffsetX;  
  18.     private int dragOffsetY;// 当前视图和屏幕的距离(这里只使用了y方向上)  
  19.   
  20.     private int upScrollBounce;// 拖动的时候,开始向上滚动的边界  
  21.     private int downScrollBounce;// 拖动的时候,开始向下滚动的边界  
  22.     private int tempChangeId;  
  23.   
  24.     private boolean isDoTouch = false;  
  25.     private boolean hasAdd=false;  
  26. //=========================================================================================================  
  27.     public DragGridViewEx(Context context) {  
  28.         super(context);  
  29.         // TODO 自动生成的构造函数存根  
  30.     }  
  31.     public DragGridViewEx(Context context, AttributeSet attrs) {  
  32.         super(context, attrs);  
  33.         // TODO 自动生成的构造函数存根  
  34.     }  
  35.     public DragGridViewEx(Context context, AttributeSet attrs, int defStyle) {  
  36.         super(context, attrs, defStyle);  
  37.         // TODO 自动生成的构造函数存根  
  38.     }  
  39.       
  40. //==========================================================================================================  
  41.     public void setDoTouch(boolean b){  
  42.         this.isDoTouch=b;  
  43.         this.hasAdd=false;  
  44.     }  
  45.     @Override  
  46.     public boolean onInterceptTouchEvent(MotionEvent ev) {  
  47.            
  48.         {  
  49.             if (ev.getAction() == MotionEvent.ACTION_DOWN) {  
  50.                 {  
  51.                     int x = (int) ev.getX();  
  52.                     int y = (int) ev.getY();  
  53.                     this.tempChangeId=dragSrcPosition = dragPosition = pointToPosition(x, y);  
  54.                       
  55.                     System.out.println("getY()="+y+","+"dragPosition="+dragPosition);  
  56.                     System.out.println("getFirstVisiblePosition()="+getFirstVisiblePosition());  
  57.                       
  58.                     // 无效不进行处理  
  59.                     if (dragPosition == AdapterView.INVALID_POSITION) {  
  60.                         return super.onInterceptTouchEvent(ev);  
  61.                     }  
  62.   
  63.                     // 获取当前位置的视图(可见状态)  
  64.                     itemView = getChildAt(dragPosition-getFirstVisiblePosition());  
  65.   
  66.                     dragPointX = x - itemView.getLeft();  
  67.                     dragPointY = y - itemView.getTop();   //不可见的项不算;  
  68.                       
  69.                     dragOffsetX = (int) (ev.getRawX() - x);  
  70.                     dragOffsetY = (int) (ev.getRawY() - y);  
  71.   
  72.                     //每个项中可能有其他的文字之类的东西,所以要获取 R.id.drag_gridview_image;  
  73.                     dragger = itemView.findViewById(R.id.drag_gridview_image);  
  74.   
  75.                     if (dragger != null &&dragPointX>dragger.getLeft()  
  76.                                         &&dragPointX<dragger.getRight()  
  77.                                         &&dragPointY>dragger.getTop()  
  78.                                         &&dragPointY<dragger.getBottom()) {  
  79.   
  80.                         upScrollBounce = getHeight() / 4;      // 取得向上滚动的边际,大概为该控件的1/3  
  81.                         downScrollBounce = getHeight() * 3 / 4;// 取得向下滚动的边际,大概为该控件的2/3  
  82.                           
  83.                         System.out.println("Here....");  
  84.                           
  85.                         itemView.setDrawingCacheEnabled(true);// 开启cache.     
  86.                             bm= Bitmap.createBitmap(itemView.getDrawingCache());// 根据cache创建一个新的bitmap对象.  
  87.                         startDrag(bm, x, y);// 初始化影像;  
  88.                           
  89.                     }  
  90.                 }     
  91.             }  
  92.         }  
  93.   
  94.         return super.onInterceptTouchEvent(ev);  
  95.     }  
  96.   
  97.     private void startDrag(Bitmap bm, int x, int y) {  
  98.         // stopDrag();  
  99.         /*** 
  100.          * 初始化window. 
  101.          */  
  102.         windowParams = new WindowManager.LayoutParams();  
  103.         windowParams.gravity = Gravity.TOP| Gravity.LEFT;  
  104.         windowParams.x = x - dragPointX + dragOffsetX;  
  105.         windowParams.y = y - dragPointY + dragOffsetY;    //getTop()+dragOffset;  
  106.         windowParams.width = WindowManager.LayoutParams.WRAP_CONTENT;  
  107.         windowParams.height = WindowManager.LayoutParams.WRAP_CONTENT;  
  108.   
  109.         windowParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE// 不需获取焦点  
  110.                 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE// 不需接受触摸事件  
  111.                 | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON// 保持设备常开,并保持亮度不变。  
  112.                 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;// 窗口占满整个屏幕,忽略周围的装饰边框(例如状态栏)。此窗口需考虑到装饰边框的内容。  
  113.   
  114.           
  115.         windowParams.windowAnimations = 0;  
  116.   
  117.         imageView = new ImageView(getContext());  
  118.         imageView.setImageBitmap(bm);  
  119.         windowManager = (WindowManager) getContext().getSystemService("window");  
  120. //      windowManager.addView(imageView, windowParams);  //注意不在这里添加;  
  121.         dragImageView = imageView;  
  122.   
  123.     }  
  124. //===========================================================================================================  
  125.     /** 
  126.      * 触摸事件处理 
  127.      */  
  128.     @Override  
  129.     public boolean onTouchEvent(MotionEvent ev) {  
  130.         // item的view不为空,且获取的dragPosition有效  
  131.         if (dragImageView!=null&&dragPosition != INVALID_POSITION && isDoTouch==true) {           
  132.             if(!this.hasAdd){  
  133.                 windowManager.addView(imageView, windowParams);  
  134.                 this.hasAdd=true;  
  135.             }  
  136.   
  137.             int action = ev.getAction();  
  138.             switch (action) {  
  139.             case MotionEvent.ACTION_UP:  
  140.                 System.out.println("ACTION_UP");  
  141.                   
  142.                 if(!this.dragger.isShown()){  
  143.                     this.dragger.setVisibility(View.VISIBLE);  
  144.                     System.out.println("VISIBLE");  
  145.                 }  
  146.                   
  147.                 int upX = (int) ev.getX();  
  148.                 int upY = (int) ev.getY();  
  149.                 stopDrag();  
  150.                 onDrop(upX,upY);  
  151.                 isDoTouch=false;  //若没有这个,就不会触发onItemClick事件了  
  152.                 hasAdd=false;  
  153.                 break;  
  154.             case MotionEvent.ACTION_MOVE:  
  155.                 //System.out.println("ACTION_MOVE");  
  156.                   
  157.                 if(this.dragger.isShown()){  
  158.                     this.dragger.setVisibility(View.INVISIBLE);  
  159.                 }  
  160.                   
  161.                 int moveX = (int)ev.getX();  
  162.                 int moveY = (int) ev.getY();  
  163.                 onDrag(moveX,moveY);  
  164.                 break;  
  165.             case MotionEvent.ACTION_DOWN:  
  166.                              //longClick之后不会执行;  
  167.                 System.out.println("ACTION_DOWN");  
  168.                 int downX = (int)ev.getX();  
  169.                 int downY = (int) ev.getY();  
  170.                   
  171.                 break;  
  172.             default:  
  173.                 break;  
  174.             }  
  175.               
  176.             return true;   
  177.         }  
  178.   
  179.         return super.onTouchEvent(ev);  
  180.     }  
  181. //=======================================================================================================  
  182.     public void onDrag(int x, int y) {  
  183.   
  184.         if (dragImageView != null) {  
  185.             windowParams.alpha = 0.7f;// 透明度  
  186.               
  187.             windowParams.x = x - dragPointX + dragOffsetX;  
  188.             windowParams.y = y - dragPointY + dragOffsetY;// 移动y值.//记得要加上dragOffset,windowManager计算的是整个屏幕.(标题栏和状态栏都要算上)  
  189.             windowManager.updateViewLayout(dragImageView, windowParams);// 时时移动.  
  190.         }  
  191.   
  192.         int tempPosition = pointToPosition(x, y);  
  193.         if (tempPosition != INVALID_POSITION) {  
  194.             dragPosition = tempPosition;  
  195.         }  
  196.           
  197.         onChange(x,y);  
  198.           
  199.         // 滚动    
  200.         if (y < upScrollBounce || y > downScrollBounce) {    
  201.             // 使用setSelection来实现滚动    
  202.             setSelection(dragPosition);    
  203.         }    
  204.     }  
  205.     public void onChange(int x,int y){  
  206.         if(dragPosition<getAdapter().getCount()){  
  207.             DragGVAdapter adapter = (DragGVAdapter)getAdapter();  
  208.             if(this.tempChangeId!=this.dragPosition){  
  209.                 adapter.update(tempChangeId,dragPosition);  
  210.                 this.tempChangeId=this.dragPosition;  
  211.             }  
  212.         }  
  213.           
  214.         int tempPosition=pointToPosition(x,y);  
  215.         if(tempPosition!=INVALID_POSITION){  
  216.             this.dragPosition=tempPosition;  
  217.         }  
  218.           
  219.     }  
  220.   
  221.     public void stopDrag() {  
  222.         if (dragImageView != null) {  
  223.             windowManager.removeView(dragImageView);  
  224.             dragImageView = null;  
  225.         }  
  226.     }  
  227.     public void onDrop(int x,int y) {  
  228.   
  229.   
  230.         // 数据交换  
  231.         if (dragPosition < getAdapter().getCount()) {  
  232.             DragGVAdapter adapter = (DragGVAdapter)getAdapter();  
  233.             adapter.lastUpdate();  
  234.         }  
  235.   
  236.     }  
  237.   
  238. }  

DragGVAdapter.java文件:

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. package com.smiling.draggridview;  
  2.   
  3. import java.util.ArrayList;  
  4.   
  5. import android.content.Context;  
  6. import android.view.LayoutInflater;  
  7. import android.view.View;  
  8. import android.view.ViewGroup;  
  9. import android.widget.BaseAdapter;  
  10. import android.widget.ImageView;  
  11.   
  12. public class DragGVAdapter extends BaseAdapter{  
  13.   
  14.     private Context context;  
  15.     private ArrayList<Integer> arrayDrawables;  
  16.     private boolean isHide=false;  
  17.     private int endPosition=-1;  
  18.       
  19.     public DragGVAdapter(Context c,ArrayList<Integer> pics){  
  20.         this.context=c;  
  21.         this.arrayDrawables=pics;  
  22.     }  
  23.       
  24.     @Override  
  25.     public int getCount() {  
  26.         // TODO 自动生成的方法存根  
  27.         return this.arrayDrawables.size();  
  28.     }  
  29.   
  30.     @Override  
  31.     public Object getItem(int arg0) {  
  32.         // TODO 自动生成的方法存根  
  33.         return null;  
  34.     }  
  35.   
  36.     @Override  
  37.     public long getItemId(int arg0) {  
  38.         // TODO 自动生成的方法存根  
  39.         return arg0;  
  40.     }  
  41.   
  42.     @Override  
  43.     public View getView(int position, View v, ViewGroup vg) {  
  44.         // TODO 自动生成的方法存根  
  45.         LayoutInflater inflater=LayoutInflater.from(context);  
  46.         v=inflater.inflate(R.layout.drag_gridview_item,null);  
  47.         System.out.println("POSITION="+position);   //连续输出两次POSITION=0;  
  48.         if(position!=endPosition){  
  49.             ImageView imageview=(ImageView)v.findViewById(R.id.drag_gridview_image);  
  50.             imageview.setImageResource(this.arrayDrawables.get(position));  
  51.             imageview.setScaleType(ImageView.ScaleType.FIT_XY);  
  52.         }else if(position==endPosition){  
  53.             ImageView imageview=(ImageView)v.findViewById(R.id.drag_gridview_image);  
  54.             imageview.setImageResource(this.arrayDrawables.get(position));  
  55.             imageview.setScaleType(ImageView.ScaleType.FIT_XY);  
  56.             imageview.setVisibility(View.INVISIBLE);  
  57.         }  
  58.   
  59.         return v;  
  60.     }  
  61.     public void update(int start, int down) {  
  62.         this.endPosition=down;  
  63.         System.out.println("END="+endPosition);  
  64.         int drawable_id = arrayDrawables.get(start);  
  65.         arrayDrawables.remove(start);   
  66.         arrayDrawables.add(down, drawable_id);   
  67.         notifyDataSetChanged();   
  68.     }  
  69.   
  70.     public void lastUpdate(){  
  71.         this.endPosition=-1;  
  72.         notifyDataSetChanged();   
  73.     }  
  74.   
  75. }  

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

Sumsang S4实测截图如下:



主题推荐
android gridview arraylist 控件 数据
猜你在找
【Android 开发】:UI控件之 GridView 网格控件的使用
Android 使用开源库StickyGridHeaders来实现带sections和headers的GridView显示本地图片效果
android在Gridview实现Textview跑马灯效果
Android程序——使用GridView组件实现如下图所示的效果
Android中利用GridView实现水平和垂直均有滚动条的表格效果
Android HorizontalScrollView结合GridView实现类似网易新闻那样的栏目滑动效果
Android中GridView的书架效果实现
Android中利用GridView实现水平和垂直均有滚动条的表格效果
android 抽屉效果,内容GridView来实现单行滑动
Android GridView实现多种不同布局样式显示数据
id="ad_frm_0" frameborder="0" scrolling="no" src="http://blog.youkuaiyun.com/common/ad.html?t=4&containerId=ad_cen&frmId=ad_frm_0" style="border-width: 0px; overflow: hidden; width: 984px; height: 90px;">
查看评论
7楼  itongworld 2014-01-30 15:05发表 [回复]
对于没有及时发送代码的网友说声SORRY,下载链接如下
http://download.youkuaiyun.com/detail/u010129564/6892329

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值