您的位置:首页 > 移动开发 > Android开发

Android 可拖拽的GridView效果实现, 长按可拖拽删除数据源

2015-10-16 15:00 459 查看
感谢这个作者的博客:Android 可拖拽的GridView效果实现, 长按可拖拽和item实时交换

作为新手,在这个的基础上,简单修改,完成自己想要的功能:长按,移到垃圾桶,删除数据。



主要思路是:1.获取到用户长按的操作

2.获取按下的图片的bitmap以及移动的时候动态刷新镜像

3 action_up的时候判断镜像的位置,进入是否删除逻辑

自定义控件

package com.leafact.GridView;

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;
import android.widget.Toast;

/**
 * 长按能选中item的,丢入垃圾箱的gridView
 * 
 * @author leafact
 * 
 */
public class MoveGridView extends GridView {

	private WindowManager mWindowManager;
	/**
	 * item镜像的布局参数
	 */
	private WindowManager.LayoutParams mWindowLayoutParams;
	/**
	 * 震动器
	 */
	private Vibrator mVibrator;
	// 震动的时间,默认为100ms
	private long vibratorMs = 100;
	// 设置长按时间为1秒
	private long responseMS = 1000;
	private static boolean isMove = false;

	// 按下去的x,y
	private int mDownX = 0;
	private int mDownY = 0;
	// 移动的时候的x,y
	private int mMoveX = 0;
	private int mMoveY = 0;
	// 抬起的x,y
	private int mUpX = 0;
	private int mUpY = 0;
	private int mPoint2ItemTop;
	private int mPoint2ItemLeft;
	private int mOffset2Top;
	private int mOffset2Left;
	/**
	 * 状态栏的高度
	 */
	private int mStatusHeight;

	public MoveGridView(Context context, AttributeSet attrs) {
		super(context, attrs);
		mVibrator = (Vibrator) context
				.getSystemService(Context.VIBRATOR_SERVICE);
		mWindowManager = (WindowManager) context
				.getSystemService(Context.WINDOW_SERVICE);
		mStatusHeight = getStatusHeight(context); // 获取状态栏的高度
	}

	// 要移动的item的位置,默认为INVALID_POSITION=-1
	private int mMovePosition = INVALID_POSITION;
	/**
	 * 刚开始拖拽的item对应的View
	 */
	private View mStartMoveItemView = null;
	private ImageView mMoveImageView = null;
	private Bitmap mMoveBitmap;
	private Handler mHandler = new Handler();
	// 判断是否能开始移动元素
	private Runnable mLongClickRunnable = new Runnable() {

		@Override
		public void run() {
			isMove = true;
			mVibrator.vibrate(vibratorMs);
			// 根据我们按下的点显示item镜像
			createDragImage(mMoveBitmap, mDownX, mDownY);
		}
	};

	@Override
	public boolean onTouchEvent(MotionEvent ev) {
		switch (ev.getAction()) {
		case MotionEvent.ACTION_DOWN:
			mDownX = (int) ev.getX();
			mDownY = (int) ev.getY();
			System.out.println("ACTION_DOWN");
			// 根据按下的X,Y坐标获取所点击item的position
			mMovePosition = pointToPosition(mDownX, mDownY);
			// 如果选中的为非法的位置。则不处理消息
			if (mMovePosition == AdapterView.INVALID_POSITION) {
				break;
			}
			mHandler.postDelayed(mLongClickRunnable, responseMS);
			mStartMoveItemView = getChildAt(mMovePosition
					- getFirstVisiblePosition());
			mPoint2ItemTop = mDownY - mStartMoveItemView.getTop();
			mPoint2ItemLeft = mDownX - mStartMoveItemView.getLeft();

			mOffset2Top = (int) (ev.getRawY() - mDownY);
			mOffset2Left = (int) (ev.getRawX() - mDownX);

			// 开启mMoveItemView绘图缓存
			mStartMoveItemView.setDrawingCacheEnabled(true);
			// 获取mMoveItemView在缓存中的Bitmap对象
			mMoveBitmap = Bitmap.createBitmap(mStartMoveItemView
					.getDrawingCache());
			// 这一步很关键,释放绘图缓存,避免出现重复的镜像
			mStartMoveItemView.destroyDrawingCache();

			break;
		case MotionEvent.ACTION_MOVE:
			mMoveX = (int) ev.getX();
			mMoveY = (int) ev.getY();

			// 如果我们在按下的item上面移动,只要不超过item的边界我们就不移除mRunnable
			// 依然能监听到longClick
			if (!isTouchInItem(mStartMoveItemView, mMoveX, mMoveY)) {
				mHandler.removeCallbacks(mLongClickRunnable);
			}

			// //禁止Gridview侧边进行滑动,移动的时候不许发生侧滑事件
			if (isMove) {
				onDragItem(mMoveX, mMoveY);
				return true;
			}
			break;
		case MotionEvent.ACTION_UP:
			mUpX = (int) ev.getX();
			mUpY = (int) ev.getY();
			mHandler.removeCallbacks(mLongClickRunnable);
			if(isMove){
				deleteIfNeed();
			}
			removeDragImage();
			isMove = false;
			break;
		default:
			break;
		}
		return super.onTouchEvent(ev);
	}

	/**
	 * 判断是否要删除,满足条件删除
	 */
	private void deleteIfNeed() {
		int y = mUpY - mPoint2ItemTop + mOffset2Top
				- mStatusHeight;
		if(y<50){
			if(mUninstallListener!=null)
			mUninstallListener.onUninstallListener(mMovePosition);
		}
	}

	/**
	 * 是否点击在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;
	}

	/**
	 * 创建拖动的镜像
	 * 
	 * @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;

		mMoveImageView = new ImageView(getContext());
		mMoveImageView.setImageBitmap(bitmap);
		mWindowManager.addView(mMoveImageView, mWindowLayoutParams);
	}

	/**
	 * 从界面上面移动拖动镜像
	 */
	private void removeDragImage() {
		if (mMoveImageView != null) {
			mWindowManager.removeView(mMoveImageView);
			mMoveImageView = 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(mMoveImageView, mWindowLayoutParams); // 更新镜像的位置
	}

	/**
	 * 获取状态栏的高度
	 * 
	 * @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;
	}

	/**
	 * 设置响应拖拽的毫秒数,默认是1000毫秒
	 * 
	 * @param responseMS
	 */
	public void setResponseMS(long responseMS) {
		this.responseMS = responseMS;
	}

	/**
	 * 设置震动时间的毫秒数,默认是1000毫秒
	 * 
	 * @param responseMS
	 */
	public void setVibrator(long vibratorMs) {
		this.vibratorMs = vibratorMs;
	}
	public void setOnUninstallListener(UninstallListener l){
		mUninstallListener=l;
	};
	private UninstallListener mUninstallListener;

}


MainActivity.java

package com.example.gridviewmovedemo;

import java.util.ArrayList;
import java.util.HashMap;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.SimpleAdapter;

import com.leafact.GridView.MoveGridView;
import com.leafact.GridView.UninstallListener;

public class MainActivity extends Activity {
	private MoveGridView mMoveGridView;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		mMoveGridView = (MoveGridView) findViewById(R.id.gridview);
		final ArrayList<HashMap<String, Object>> lstImageItem = new ArrayList<HashMap<String, Object>>();
		for (int i = 0; i < 10; i++) {
			HashMap<String, Object> map = new HashMap<String, Object>();
			map.put("ItemText", "NO." + String.valueOf(i));// 按序号做ItemText
			lstImageItem.add(map);
		}
		final SimpleAdapter saImageItems = new SimpleAdapter(this,
				lstImageItem,// 数据来源
				R.layout.gridview_item,
				// 动态数组与ImageItem对应的子项
				new String[] { "ItemText" },
				// ImageItem的XML文件里面的一个ImageView,两个TextView ID
				new int[] { R.id.ItemText });
		// 添加并且显示
		mMoveGridView.setAdapter(saImageItems);
		//监听到卸载删除数据
		mMoveGridView.setOnUninstallListener(new UninstallListener() {

			@Override
			public void onUninstallListener(int position) {
				lstImageItem.remove(position);
				saImageItems.notifyDataSetChanged();
			}
		});
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

}


UninstallListener.java

package com.leafact.GridView;

public interface UninstallListener {
	void onUninstallListener(int position);
}


activity_main.xml

<LinearLayout 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"
    android:background="#fff"
    android:orientation="vertical"
    tools:context=".MainActivity" >

    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="100dip"
        android:background="#ccc" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="fill_parent"
            android:layout_centerHorizontal="true"
            android:gravity="center"
            android:text="卸载"
            android:textColor="#fff"
            android:textSize="28sp" />
    </RelativeLayout>

    <com.leafact.GridView.MoveGridView
        android:id="@+id/gridview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:horizontalSpacing="5dip"
        android:numColumns="3"
        android:verticalSpacing="5dip" />

</LinearLayout>


gridview_item.xml

<?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="#2248DD" >

    <TextView
        android:id="@+id/ItemText"
        android:layout_width="wrap_content"
        android:layout_height="100dip"
        android:layout_centerHorizontal="true"
        android:gravity="center" >
    </TextView>

</RelativeLayout>


封装的有点问题,后期要修改一下,简单记录一下吧
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: