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

所属分类: 软件编程 / Android 阅读数: 1940
收藏 0 赞 0 分享
写在前面的话
本篇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>

源码下载
更多精彩内容其他人还在看

使用ViewPager实现android软件使用向导功能实现步骤

现在的大部分android软件,都是使用说明,就是第一次使用该软件时,会出现向导,可以左右滑动,然后就进入应用的主界面了,下面我们就实现这个功能
收藏 0 赞 0 分享

android在异步任务中关闭Cursor的代码方法

android在异步任务中如何关闭Cursor?在我们开发应用的时候,很多时候会遇到这种问题,下面我们就看看代码如何实现
收藏 0 赞 0 分享

Android自定义桌面功能代码实现

android自定义桌面其实很简单,看一个例子就明白了
收藏 0 赞 0 分享

android将图片转换存到数据库再从数据库读取转换成图片实现代码

有时候我们想把图片存入到数据库中,尽管这不是一种明智的选择,但有时候还是不得以会用到,下面说说将图片转换成byte[]数组存入到数据库中去,并从数据库中取出来转换成图像显示出来
收藏 0 赞 0 分享

TextView显示系统时间(时钟功能带秒针变化

用System.currentTimeMillis()可以获取系统当前的时间,我们可以开启一个线程,然后通过handler发消息,来实时的更新TextView上显示的系统时间,可以做一个时钟的功能
收藏 0 赞 0 分享

Android用ListView显示SDCard文件列表的小例子

本文简单实现了用ListView显示SDCard文件列表,目录的回退等功能暂不讨论,获取文件列表,files即为所选择目录下的所有文件列表
收藏 0 赞 0 分享

Android拦截外拨电话程序示例

这篇文章主要介绍了Android拦截外拨电话的示例,大家参考使用吧
收藏 0 赞 0 分享

通过Html网页调用本地安卓(android)app程序代码

如何使用html网页和本地app进行传递数据呢?经过研究,发现还是有方法的,总结了一下,大致有一下几种方式
收藏 0 赞 0 分享

android Textview文字监控(Textview使用方法)

以手机号充值为例,当用户输入最后一位数时候,进行汇率的变换,本文就实现类似这样的功能
收藏 0 赞 0 分享

Android ListView长按弹出菜单二种实现方式示例

这篇文章主要介绍了Android ListView长按弹出菜单的方法,大家参考实现
收藏 0 赞 0 分享
查看更多