自定义GridView并且实现拖拽(附源码)

 更新时间:2013年06月07日 17:06:30   作者:  
本文实现了GridView的拖拽功能,原理很简单只是在交换位置上记录了X轴的相关坐标,计算了X轴的相关变量,实例代码如下,感兴趣的额朋友可以参考下哈
写在前面的话
本篇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;
}
}
}

2、DragGridView.java
复制代码 代码如下:

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

3、activity_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"
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>

4、drag_grid_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: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>

源码下载

相关文章

  • Android 实现九宫格抽奖功能

    Android 实现九宫格抽奖功能

    这篇文章主要介绍了Android 实现九宫格抽奖功能,帮助大家更好的理解和学习使用Android,感兴趣的朋友可以了解下
    2021-03-03
  • android 软键盘的POPUP布局的问题解决

    android 软键盘的POPUP布局的问题解决

    这篇文章主要介绍了android 软键盘的POPUP布局的问题解决,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-10-10
  • Pagerslidingtabstrip菜单标题栏制作方法

    Pagerslidingtabstrip菜单标题栏制作方法

    这篇文章主要为大家详细介绍了Pagerslidingtabstrip菜单标题栏的制作方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-10-10
  • Android编程实现应用强制安装到手机内存的方法

    Android编程实现应用强制安装到手机内存的方法

    这篇文章主要介绍了Android编程实现应用强制安装到手机内存的方法,涉及Android中属性设置的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-11-11
  • Android实现仿今日头条点赞动画效果实例

    Android实现仿今日头条点赞动画效果实例

    我想看到今日头条的点赞效果,应该都觉得很绚丽吧,下面这篇文章主要给大家介绍了关于Android实现仿今日头条点赞动画效果的相关资料,文中通过示例代价介绍的非常详细,需要的朋友可以参考下
    2022-02-02
  • Android MVP BaseFragment 通用式封装的实现

    Android MVP BaseFragment 通用式封装的实现

    这篇文章主要介绍了Android MVP BaseFragment 通用式封装的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-08-08
  • 通过FancyView提供 Android 酷炫的开屏动画实例代码

    通过FancyView提供 Android 酷炫的开屏动画实例代码

    这篇文章主要介绍了通过FancyView提供 Android 酷炫的开屏动画的实现代码,需要的朋友可以参考下
    2017-12-12
  • Android SurfaceView与TextureView使用方法详细讲解

    Android SurfaceView与TextureView使用方法详细讲解

    SurfaceView和TextureView都继承View,与普通的View不同的是,它俩可以在独立线程中绘制渲染,性能更高,所以常被应用在对绘制速率要求比较高的场景,比如相机预览,视频播放等等
    2022-10-10
  • Android实现多级树形菜单并支持多选功能

    Android实现多级树形菜单并支持多选功能

    这篇文章主要为大家详细介绍了Android实现多级树形菜单并支持多选功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-07-07
  • activity控制对话框风格、显示大小与位置

    activity控制对话框风格、显示大小与位置

    对于对话框风格大家普遍使用PopupWindow,也有许多朋友开发设计时使用的是activity对话框方式,因此,本文对如何通过activity实现与PopupWindow相同的效果进行详细介绍,具有很好的参考价值,需要的朋友一起来看下吧
    2016-12-12

最新评论