一.项目要求要长按后拖拽的效果.
网络上有一份代码,存在两个尚未解决的问题:
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
本文介绍如何在Android中实现GridView的长按拖拽功能。原始代码存在点击即拖拽和滑动干扰问题,经过改进,实现了长按后才显示拖拽效果,并解决了拖动到屏幕边缘时界面不滚动的问题。提供了完整的修改后代码供下载。
805

被折叠的 条评论
为什么被折叠?



