GridView长按拖拽Item效果(android)

本文介绍如何在Android中实现GridView的长按拖拽功能。原始代码存在点击即拖拽和滑动干扰问题,经过改进,实现了长按后才显示拖拽效果,并解决了拖动到屏幕边缘时界面不滚动的问题。提供了完整的修改后代码供下载。

一.项目要求要长按后拖拽的效果.

网络上有一份代码,存在两个尚未解决的问题:

1)    点击后就拖拽,并且如果你往下滑的时候,界面会受干扰,因为他用的是Action.Move

2)   当拖拽的View跑到快接近手机屏幕边缘时,GridView没有向下移动.


二.于是经过本人修改,实现了长按后才出现拖拽界面的效果,代码如下:

package com.pl;

import com.pl.MainActivity.ImageAdapter;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.PixelFormat;
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;

public class DragGridView extends GridView
{

	private int							dragPosition;	// 开始拖拽的位置
	private int							dropPosition;	// 结束拖拽的位置
	private int							dragPointX;	// 相对于item的x坐标
	private int							dragPointY;	// 相对于item的y坐标
	private int							dragOffsetX;
	private int							dragOffsetY;
	private ImageView					dragImageView;	// 拖动item的preview

	private WindowManager				windowManager;
	private WindowManager.LayoutParams	windowParams;

	private int							itemHeight;

	public DragGridView(Context context, AttributeSet attrs)
	{
		super(context, attrs);
	}

	boolean	flag	= false;

	public void setLongFlag(boolean temp)
	{
		flag = temp;
	}

	public boolean setOnItemLongClickListener(final MotionEvent ev)
	{
		this.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener()
		{
			@Override
			public boolean onItemLongClick(AdapterView<?> arg0, View arg1,
					int arg2, long arg3)
			{
				// onInterceptTouchEvent(ev);
				// TODO Auto-generated method stub
				L.l("============on Long Click=========");
				L.l("============X:" + ev.getX() + " Y:" + ev.getY());

				int x = (int) ev.getX();
				int y = (int) ev.getY();
				L.l("============X:" + x + " Y:" + y);
				dragPosition = dropPosition = pointToPosition(x, y);
				System.out.println(dragPosition);
				if (dragPosition == AdapterView.INVALID_POSITION)
				{

				}
				ViewGroup itemView = (ViewGroup) getChildAt(dragPosition
						- getFirstVisiblePosition());
				// 得到当前点在item内部的偏移量 即相对于item左上角的坐标
				dragPointX = x - itemView.getLeft();
				dragPointY = y - itemView.getTop();

				dragOffsetX = (int) (ev.getRawX() - x);
				dragOffsetY = (int) (ev.getRawY() - y);
				
				itemHeight=itemView.getHeight();

				L.l("========================y:" + y + " getRawY:"
						+ ev.getRawY());

				// 解决问题3
				// 每次都销毁一次cache,重新生成一个bitmap
				itemView.destroyDrawingCache();
				itemView.setDrawingCacheEnabled(true);
				Bitmap bm = Bitmap.createBitmap(itemView.getDrawingCache());
				// 建立item的缩略图
				startDrag(bm, x, y);
				return false;
			};
		});
		return super.onInterceptTouchEvent(ev);
	}

	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev)
	{
		if (ev.getAction() == MotionEvent.ACTION_DOWN)
		{
			return setOnItemLongClickListener(ev);
		}
		return super.onInterceptTouchEvent(ev);
	}

	private void startDrag(Bitmap bm, int x, int y)
	{
		stopDrag();

		windowParams = new WindowManager.LayoutParams();
		System.out.println("X: " + x + " dragPointX: " + dragPointX
				+ " dragOffsetX: " + dragOffsetX);
		windowParams.gravity = Gravity.TOP | Gravity.LEFT;// 这个必须加
		// 得到preview左上角相对于屏幕的坐标
		windowParams.x = x - dragPointX + dragOffsetX;
		windowParams.y = y - dragPointY + dragOffsetY;
		// L.l("==================windowParams.y==============="+windowParams.y);
		// 设置宽和高
		windowParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
		windowParams.width = 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.format = PixelFormat.TRANSLUCENT;
		windowParams.windowAnimations = 0;

		ImageView iv = new ImageView(getContext());
		iv.setImageBitmap(bm);
		windowManager = (WindowManager) getContext().getSystemService(
				Context.WINDOW_SERVICE);// "window"
		windowManager.addView(iv, windowParams);
		dragImageView = iv;
	}

	@Override
	public boolean onTouchEvent(MotionEvent ev)
	{
		if (dragImageView != null
				&& dragPosition != AdapterView.INVALID_POSITION)
		{
			int x = (int) ev.getX();
			int y = (int) ev.getY();
			switch (ev.getAction())
			{
				case MotionEvent.ACTION_MOVE:
					onDrag(x, y);
					break;
				case MotionEvent.ACTION_UP:
					stopDrag();
					onDrop(x, y);
					break;
			}
		}
		return super.onTouchEvent(ev);
	}

	private void onDrag(int x, int y)
	{
		if (dragImageView != null)
		{
			windowParams.alpha = 0.6f;
			windowParams.x = x - dragPointX + dragOffsetX;
			windowParams.y = y - dragPointY + dragOffsetY;
			// L.l("=================windowParams.y=====000========"+windowParams.y);
			windowManager.updateViewLayout(dragImageView, windowParams);
		}

		int tempScrollX = x - dragPointX + dragOffsetX;
		int tempScrollY = y - dragPointY + dragOffsetY;

		if (tempScrollY +itemHeight> 600)
		{
			this.scrollTo(0, tempScrollY);
		}
		else
			if (pointToPosition(x, y) > 2)
			{

				this.scrollTo(0, tempScrollY - 300);
			}

	}

	private void onDrop(int x, int y)
	{
		int tempPosition = pointToPosition(x, y);
		if (tempPosition != AdapterView.INVALID_POSITION)
		{
			dropPosition = tempPosition;
		}
		if (dropPosition != dragPosition)
		{
			System.out.println("dragPosition: " + dragPosition
					+ " dropPosition: " + dropPosition);
			ImageAdapter adapter = (ImageAdapter) this.getAdapter();
			adapter.exchange(dragPosition, dropPosition);

			// 解决问题3
			/*
			 * ViewGroup itemView1 = (ViewGroup)getChildAt(dragPosition - getFirstVisiblePosition()); ViewGroup
			 * itemView2 = (ViewGroup)getChildAt(dropPosition - getFirstVisiblePosition());
			 * itemView1.destroyDrawingCache(); itemView2.destroyDrawingCache();
			 */
		}
	}

	private void stopDrag()
	{
		if (dragImageView != null)
		{
			windowManager.removeView(dragImageView);
			dragImageView = null;
		}
	}

}

package com.pl;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;


public class MainActivity extends Activity {
    private DragGridView gv;
    private List<String> list = new ArrayList<String>();
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        initData();
        
        gv = (DragGridView)findViewById(R.id.drag_grid);
        gv.setAdapter(new ImageAdapter(this));
        gv.setOnItemClickListener(new OnItemClickListener()
		{

			@Override
			public void onItemClick(AdapterView<?> parent, View view,
					int position, long id)
			{
				// TODO Auto-generated method stub
			    L.l("============onItemClick====position:"+position);
			}
        	
		} );
        

    }
    
    private void initData(){
        for(int i=1;i<100;i++){
            list.add(""+i);
        }
    }
    
    public class ImageAdapter extends BaseAdapter{
        private Context mContext;
        private LayoutInflater lif;
        public ImageAdapter(Context c){
            mContext = c;
            lif = LayoutInflater.from(c);
        }
        
        public int getCount() {
            return list.size();
        }

        public Object getItem(int position) {
            // TODO Auto-generated method stub
            return list.get(position);
        }

        public long getItemId(int position) {
            // TODO Auto-generated method stub
            return position;
        }

        /**
         * 遇到的问题:
         * 1、删除错了 会有重复的图片
         * 这个是由 remove引起的
         *  删除时 我们先删除了小的position
         * 比如说 startPosition = 2;endPosition = 3;
         * 当我先删startPosition时 这时 删除前position为3的项 已经是position为2了 
         * 2、数组越界 异常
         * 这个是由 add引起的
         * 比如说 startPosition = 8;endPosition = 7;
         * 一共gridview有9个元素 也就是说8 已经是最大的了
         * 当删除完后 你先增加爱 startposition时  就会异常了
         * 3、preview问题
         * 当我拖拽互换几次后 机会出现 当前的图片 显示的是另一个图片的preview
         * 
         * 得调用 destroyDrawingCache
         * @param startPosition
         * @param endPosition
         */
        public void exchange(int startPosition, int endPosition){
            //比较一下 使startPosition永远小于endPosition的值 解决问题1 ,2
            if(startPosition > endPosition){
                int temp = endPosition;
                endPosition = startPosition;
                startPosition = temp;
            }
            Object endObject = getItem(endPosition);
            Object startObject = getItem(startPosition);
            //list.remove(endPosition);
            //list.remove(startPosition);
            System.out.println(startPosition + "========"+endPosition);
            list.set(startPosition,(String)endObject);
            list.set(endPosition,(String)startObject);
            notifyDataSetChanged();
        }
        
        public View getView(int position, View convertView, ViewGroup parent) {
            //ImageView iv;
            if(convertView==null){
                convertView = lif.inflate(R.layout.grid_item, null);
//                iv = new ImageView(mContext);
//                try{
//                Field f = (Field)R.drawable.class.getDeclaredField(list.get(position));
//                int i = f.getInt(R.drawable.class);
//                iv.setImageResource(i);
//                }catch(Exception e){
//                    e.printStackTrace();
//                }
            }
                
            try {
           
                
                TextView  textView=(TextView)convertView.findViewById(R.id.textView);
                textView.setText(list.get(position));
                ImageView  imgView=(ImageView)convertView.findViewById(R.id.image);
                imgView.setBackgroundResource(R.drawable.icon);
                
            } catch (Exception e) {
                e.printStackTrace();
            }
            return convertView;
        }
        
    }
}


三.完整代码如下下载

http://download.youkuaiyun.com/detail/synwith/3693769


评论 7
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值