自定义GridView并且实现拖拽(附源码)
写在前面的话
本篇blog实现了GridView的拖拽功能。方法和上一篇自定义ListView实现拖拽ListItem项交换位置一个原理。只是在交换位置上记录了X轴的相关坐标,计算了X轴的相关变量。
实现效果图如下
说明:
本篇给出实现代码,但是不做任何说明。如需了解请看上一篇blog:自定义ListView实现拖拽ListItem项交换位置
文件代码:
1、MainActivity.java
代码如下:
package com.jay.draggridview;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
public class MainActivity extends Activity {
private static List<String> list = null;
//自定义适配器
private DragGridAdapter adapter = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化数据
initData();
//后面用到的自定义GridView
DragGridView dragGridView = (DragGridView)findViewById(R.id.drag_grid);
adapter = new DragGridAdapter(this, list);
dragGridView.setAdapter(adapter);
}
public void initData(){
list = new ArrayList<String>();
for(int i= 0 ; i < 12 ; i++){
list.add("grid_"+i%12);
}
}
public static class DragGridAdapter extends ArrayAdapter<String>{
public DragGridAdapter(Context context, List<String> objects) {
super(context, 0, objects);
}
public List<String> getList(){
return list;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
if(view==null){
view = LayoutInflater.from(getContext()).inflate(R.layout.drag_grid_item, null);
}
try {
Log.v("item", "------"+getItem(position));
//根据文件名获取资源文件夹中的图片资源
Field f= (Field)R.drawable.class.getDeclaredField(getItem(position));
int i=f.getInt(R.drawable.class);
ImageView imageview= (ImageView)view.findViewById(R.id.drag_grid_item_image);
imageview.setImageResource(i);
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return view;
}
}
}
package com.jay.draggridview;
import com.jay.draggridview.MainActivity.DragGridAdapter;
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;
import android.widget.Toast;
public class DragGridView extends GridView{
//定义基本的成员变量
private ImageView dragImageView;
private int dragSrcPosition;
private int dragPosition;
//x,y坐标的计算
private int dragPointX;
private int dragPointY;
private int dragOffsetX;
private int dragOffsetY;
private WindowManager windowManager;
private WindowManager.LayoutParams windowParams;
private int scaledTouchSlop;
private int upScrollBounce;
private int downScrollBounce;
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();
dragSrcPosition = dragPosition = pointToPosition(x, y);
if(dragPosition==AdapterView.INVALID_POSITION){
return super.onInterceptTouchEvent(ev);
}
ViewGroup itemView = (ViewGroup) getChildAt(dragPosition-getFirstVisiblePosition());
dragPointX = x - itemView.getLeft();
dragPointY = y - itemView.getTop();
dragOffsetX = (int) (ev.getRawX() - x);
dragOffsetY = (int) (ev.getRawY() - y);
View dragger = itemView.findViewById(R.id.drag_grid_item_drag);
//如果选中拖动图标
if(dragger!=null&&dragPointX>dragger.getLeft()&&dragPointX<dragger.getRight()&&dragPointY>dragger.getTop()&&dragPointY<dragger.getBottom()+20){
upScrollBounce = Math.min(y-scaledTouchSlop, getHeight()/4);
downScrollBounce = Math.max(y+scaledTouchSlop, getHeight()*3/4);
itemView.setDrawingCacheEnabled(true);
Bitmap bm = Bitmap.createBitmap(itemView.getDrawingCache());
startDrag(bm, x, y);
}
return false;
}
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
if(dragImageView!=null&&dragPosition!=INVALID_POSITION){
int action = ev.getAction();
switch(action){
case MotionEvent.ACTION_UP:
int upX = (int)ev.getX();
int upY = (int)ev.getY();
stopDrag();
onDrop(upX,upY);
break;
case MotionEvent.ACTION_MOVE:
int moveX = (int)ev.getX();
int moveY = (int)ev.getY();
onDrag(moveX,moveY);
break;
default:break;
}
return true;
}
return super.onTouchEvent(ev);
}
public void startDrag(Bitmap bm, int x, int y){
stopDrag();
windowParams = new WindowManager.LayoutParams();
windowParams.gravity = Gravity.TOP|Gravity.LEFT;
windowParams.x = x - dragPointX + dragOffsetX;
windowParams.y = y - dragPointY + dragOffsetY;
windowParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
windowParams.height = 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 imageView = new ImageView(getContext());
imageView.setImageBitmap(bm);
windowManager = (WindowManager)getContext().getSystemService("window");
windowManager.addView(imageView, windowParams);
dragImageView = imageView;
}
public void onDrag(int x, int y){
if(dragImageView!=null){
windowParams.alpha = 0.8f;
windowParams.x = x - dragPointX + dragOffsetX;
windowParams.y = y - dragPointY + dragOffsetY;
windowManager.updateViewLayout(dragImageView, windowParams);
}
int tempPosition = pointToPosition(x, y);
if(tempPosition!=INVALID_POSITION){
dragPosition = tempPosition;
}
//滚动
if(y<upScrollBounce||y>downScrollBounce){
//使用setSelection来实现滚动
setSelection(dragPosition);
}
}
public void onDrop(int x, int y){
//为了避免滑动到分割线的时候,返回-1的问题
int tempPosition = pointToPosition(x, y);
if(tempPosition!=INVALID_POSITION){
dragPosition = tempPosition;
}
//超出边界处理
if(y<getChildAt(0).getTop()){
//超出上边界
dragPosition = 0;
}else if(y>getChildAt(getChildCount()-1).getBottom()||(y>getChildAt(getChildCount()-1).getTop()&&x>getChildAt(getChildCount()-1).getRight())){
//超出下边界
dragPosition = getAdapter().getCount()-1;
}
//数据交换
if(dragPosition!=dragSrcPosition&&dragPosition>-1&&dragPosition<getAdapter().getCount()){
DragGridAdapter adapter = (DragGridAdapter)getAdapter();
String dragItem = adapter.getItem(dragSrcPosition);
adapter.remove(dragItem);
adapter.insert(dragItem, dragPosition);
Toast.makeText(getContext(), adapter.getList().toString(), Toast.LENGTH_SHORT).show();
}
}
/***
* 停止拖动,去掉拖动时候的影像
*/
public void stopDrag(){
if(dragImageView != null){
windowManager.removeView(dragImageView);
dragImageView = null;
}
}
}
<?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"
android:background="#ffffff"
android:padding="10dip"
>
<com.jay.draggridview.DragGridView
android:id="@+id/drag_grid"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:cacheColorHint="#00000000"
android:numColumns="3"
android:stretchMode="columnWidth"
android:verticalSpacing="5dip"
android:horizontalSpacing="20dip"
android:background="#ffffff"/>
</LinearLayout>
<?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:paddingLeft="5dip"
android:paddingRight="5dip">
<ImageView android:id="@+id/drag_grid_item_image"
android:layout_margin="5dip"
android:layout_alignParentTop="true"
android:layout_width="fill_parent"
android:layout_height="60dip"/>
<ImageView android:id="@+id/drag_grid_item_drag"
android:src="@drawable/p32_24_1"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</RelativeLayout>
源码下载