2011.06.21——— android GridView的拖拽

本文介绍如何在Android中实现可拖拽的GridView,并详细解释了关键代码逻辑及问题解决方法。

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

2011.06.21——— android GridView的拖拽
参考:[url]http://www.cnblogs.com/qianxudetianxia/archive/2011/06/19/2084886.html[/url]

需求:一个可拖拽的gridview
代码:

拖拽view:


package com.lp;

import com.lp.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.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;

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

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {

if(ev.getAction()==MotionEvent.ACTION_DOWN){

int x = (int)ev.getX();
int y = (int)ev.getY();
dragPosition = dropPosition = pointToPosition(x, y);
System.out.println(dragPosition);
if(dragPosition==AdapterView.INVALID_POSITION){
return super.onInterceptTouchEvent(ev);
}
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);
//解决问题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);
}

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;
//设置宽和高
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;
windowManager.updateViewLayout(dragImageView, windowParams);
}
}

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;
}
}




}



MainActivity:

package com.lp;

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.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

public class MainActivity extends Activity {
private GridView gv;
private List<String> list = new ArrayList<String>();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

initData();

gv = (GridView)findViewById(R.id.drag_grid);
gv.setAdapter(new ImageAdapter(this));
}

private void initData(){
for(int i=1;i<10;i++){
list.add("grid_"+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 {
Field f = (Field)R.drawable.class.getDeclaredField(list.get(position));
int i = f.getInt(R.drawable.class);
ImageView iv = (ImageView)convertView.findViewById(R.id.image);
iv.setImageResource(i);
} catch (Exception e) {
e.printStackTrace();
}
// else{
// iv = (ImageView)convertView;
// }

return convertView;
}

}
}



main.xml


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<com.lp.DragGridView
android:id="@+id/drag_grid"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:cacheColorHint="#00000000"
android:numColumns="3"
android:stretchMode="columnWidth"
android:verticalSpacing="5dip"
android:horizontalSpacing="20dip"
android:background="#ffffff"/>

</LinearLayout>



grid_item.xml


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>



具体说明 请看代码 里面有详细说明
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值