Android中GridView拖拽的效果
最 近看到联想,摩托罗拉等,手机launcher中有个效果,进入mainmenu后,里面的应用程序的图标可以拖来拖去,所以我也参照网上给的代码,写了 一个例子。还是很有趣的,实现的流畅度没有人家的那么好,我只是模仿这种效果,我写的这个拖拽是两个图标之间进行交换,所以,当从一行的某个位置,换到下 一行的另一列的时候,发现有好几个图标都改变位置了,因为是相邻两个交换位置,所以每经过相邻的图标的时候都改变位置。先弄个雏形,以后再更新优化。
转载请标明出处:http://blog.csdn.net/wdaming1986/article/details/7436881
先看几张效果图,再来研究代码:
横行拖拽:
纵向拖拽的效果图:
下面贴上代码---->在GragGridViewApp-4-7这个工程里面:
1、在包com.cn.daming.adapter中,有三个类----->
1.1、DragAdapter.java这个类中的代码如下:
- <span style="color:#000000;FONT-SIZE: 16px">package com.cn.daming.adapter;
- import java.util.ArrayList;
- import java.util.Collections;
- import android.content.Context;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.BaseAdapter;
- public abstract class DragAdapter extends BaseAdapter {
- protected Context mContext;
- protected ArrayList<DragMessage> mlist;
- public DragAdapter(Context mContext, ArrayList<DragMessage> mlist) {
- this.mContext = mContext;
- this.mlist = mlist;
- }
- public int getCount() {
- if (this.mlist != null) {
- return this.mlist.size();
- }
- return 0;
- }
- public DragMessage getItem(int position) {
- return (DragMessage)this.mlist.get(position);
- }
- public long getItemId(int position) {
- return 0;
- }
- public void addMsg(DragMessage msg){
- this.mlist.add(msg);
- }
- final void reFlag(){
- for (DragMessage msg : this.mlist) {
- msg.flag = 0;
- }
- notifyDataSetChanged();
- }
- final void swap(int srcPosition, int dragPosition){
- Collections.swap(this.mlist, srcPosition, dragPosition);
- notifyDataSetChanged();
- }
- final void setFlag(int position, int flag){
- getItem(position).flag = flag;
- notifyDataSetChanged();
- }
- public abstract View getView(int position, View convertView, ViewGroup parent);
- }
- </span>
1.2、DragMessage.java这个类中的代码如下:
- package com.cn.daming.adapter;
- public class DragMessage {
- public static final int MOVE_FLAG = 1;
- public static final int STATIC_FLAG = 0;
- public int flag = 0;
- }
1.3、GragGridView.java核心类中的代码如下:
- package com.cn.daming.adapter;
- import android.content.Context;
- import android.graphics.Bitmap;
- import android.graphics.Color;
- import android.graphics.PixelFormat;
- import android.graphics.drawable.Drawable;
- import android.os.Handler;
- import android.os.Looper;
- import android.os.Message;
- import android.util.AttributeSet;
- import android.util.Log;
- 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 GragGridView extends GridView{
- private ImageView dragImageView;//拖动item的preview
- private WindowManager windowManager;
- private WindowManager.LayoutParams windowParams;
- private int dragSrcPosition; //开始拖拽的位置
- private int dragPosition; // 结束拖拽的位置
- private int dragPointX;//相对于item的x坐标
- private int dragPointY;//相对于item的y坐标
- private int dragOffsetX;
- private int dragOffsetY;
- private int dragImageId;
- private int itemHeight;
- private int itemWidth;
- private int moveHeight = 0;
- private int upScrollBounce;
- private int downScrollBounce;
- private int dragColor = Color.GRAY;
- private int changePosition = -1;
- private long scrollDelayMillis = 10L;
- private int middleX;
- private int middleY;
- private boolean isDrag = false;
- private RefreshHandler scrollDelayUp = new RefreshHandler(Looper.getMainLooper(), true);
- private RefreshHandler scrollDelayDown = new RefreshHandler(Looper.getMainLooper(), false);
- private int scrollHeight = 4;
- private int maxSH = 20;
- private int minSH = 4;
- public void setMoveHeight(int height) {
- this.moveHeight = height;
- }
- public void setDragColor(int color) {
- this.dragColor = color;
- }
- public void setDragImageId(int id) {
- this.dragImageId = id;
- }
- public GragGridView(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();
- this.dragSrcPosition = this.dragPosition = pointToPosition(x, y);
- if (this.dragPosition == -1) {
- return super.onInterceptTouchEvent(ev);
- }
- ViewGroup itemView = (ViewGroup)getChildAt(this.dragPosition -
- getFirstVisiblePosition());
- //得到当前点在item内部的偏移量 即相对于item左上角的坐标
- this.itemHeight = itemView.getHeight();
- this.dragPointX = (x - itemView.getLeft());
- this.dragPointY = (y - itemView.getTop());
- this.dragOffsetX = (int)(ev.getRawX() - x);
- this.dragOffsetY = (int)(ev.getRawY() - y);
- View dragger = itemView.findViewById(this.dragImageId);
- if ((dragger != null) && (x > dragger.getLeft()&& x < dragger.getRight()) &&
- (y > dragger.getTop() && y < dragger.getBottom())) {
- if(this.moveHeight <= 0 || (this.moveHeight >= getHeight()/2)) {
- this.upScrollBounce = (getHeight() / 3);
- this.downScrollBounce = (getHeight() * 2 / 3);
- } else {
- this.upScrollBounce = this.moveHeight;
- this.downScrollBounce = (getHeight() - this.moveHeight);
- }
- //解决问题3
- //每次都销毁一次cache,重新生成一个bitmap
- itemView.destroyDrawingCache();
- itemView.setDrawingCacheEnabled(true);
- Drawable background = itemView.getBackground();
- itemView.setBackgroundColor(this.dragColor);
- Bitmap bitmap = Bitmap.createBitmap(itemView.getDrawingCache());
- itemView.setBackgroundDrawable(background);
- //建立item的缩略图
- startDrag(bitmap, x, y);
- }
- return false;
- }
- return super.onInterceptTouchEvent(ev);
- }
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- if ((this.dragImageView != null) && (this.dragPosition != -1)) {
- int action = ev.getAction();
- int moveY = (int)ev.getY();
- int moveX = (int)ev.getX();
- 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:
- if (moveX <= 0)
- this.middleX = 0;
- else if (moveX >= getWidth())
- this.middleX = getWidth();
- else {
- this.middleX = moveX;
- }
- if (moveY <= 0)
- this.middleY = 0;
- else if (moveY >= getHeight())
- this.middleY = getHeight();
- else {
- this.middleY = moveY;
- }
- dragPositionChanged();
- onDrag(moveX, moveY);
- }
- return true;
- }
- return super.onTouchEvent(ev);
- }
- private void onDrag(int x, int y) {
- if (this.dragImageView != null) {
- this.windowParams.alpha = 0.8F;
- if (this.middleX - this.dragPointX <= 0)
- this.windowParams.x = this.dragOffsetX;
- else if (this.middleX - this.dragPointX >= getWidth() - this.itemWidth)
- this.windowParams.x = (getWidth() - this.itemWidth + this.dragOffsetX);
- else {
- this.windowParams.x = (this.middleX - this.dragPointX + this.dragOffsetX);
- }
- if (this.middleY - this.dragPointY <= 0)
- this.windowParams.y = this.dragOffsetY;
- else if (this.middleY - this.dragPointY >= getHeight() - this.itemHeight)
- this.windowParams.y = (getHeight() - this.itemHeight + this.dragOffsetY);
- else {
- this.windowParams.y = (this.middleY - this.dragPointY + this.dragOffsetY);
- }
- this.windowManager.updateViewLayout(this.dragImageView, this.windowParams);
- }
- int tempPosition = pointToPosition(this.middleX, this.middleY);
- Log.v("daming", "GragGridView ---> 177 tempPosition == "+tempPosition);
- if (tempPosition != -1) {
- this.dragPosition = tempPosition;
- }
- if ((y >= this.upScrollBounce) && (y <= this.downScrollBounce)) {
- this.isDrag = false;
- return;
- }
- if (y < this.upScrollBounce) {
- float a = this.upScrollBounce - this.middleY;
- float b = this.upScrollBounce;
- float c = a / b;
- this.scrollHeight = (int)(c * (this.maxSH - this.minSH) + this.minSH);
- this.isDrag = true;
- this.scrollDelayUp.sleep(0L);
- } else if (y > this.downScrollBounce) {
- float a = this.middleY - this.downScrollBounce;
- float b = this.upScrollBounce;
- float c = a / b;
- this.scrollHeight = (int)(c * (this.maxSH - this.minSH) + this.minSH);
- this.isDrag = true;
- this.scrollDelayDown.sleep(0L);
- }
- }
- private void startDrag(Bitmap bm, int x, int y) {
- stopDrag();
- this.windowParams = new WindowManager.LayoutParams();
- //Gravity.TOP|Gravity.LEFT;这个必须加
- this.windowParams.gravity = Gravity.TOP|Gravity.LEFT;
- //得到preview左上角相对于屏幕的坐标
- this.windowParams.x = (x - this.dragPointX + this.dragOffsetX);
- this.windowParams.y = (y - this.dragPointY + this.dragOffsetY);
- //设置拖拽item的宽和高
- this.windowParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
- this.windowParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
- this.windowParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
- | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
- | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
- this.windowParams.format = PixelFormat.TRANSLUCENT;
- this.windowParams.windowAnimations = 0;
- ImageView imageView = new ImageView(getContext());
- imageView.setImageBitmap(bm);
- this.windowManager = ((WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE));//“window”
- this.windowManager.addView(imageView, this.windowParams);
- this.dragImageView = imageView;
- }
- private void stopDrag() {
- if (this.dragImageView != null) {
- this.windowManager.removeView(this.dragImageView);
- this.dragImageView = null;
- }
- this.changePosition = -1;
- this.isDrag = false;
- }
- private void dragPositionChanged(){
- DragAdapter adapter = (DragAdapter)getAdapter();
- if (this.changePosition != this.dragPosition) {
- if (this.changePosition == -1)
- {
- this.changePosition = this.dragPosition;
- adapter.setFlag(this.changePosition, 1);
- return;
- }
- adapter.swap(this.changePosition, this.dragPosition);
- this.changePosition = this.dragPosition;
- }
- }
- public void setMaxSH(int sh){
- this.maxSH = sh;
- }
- public void setMinSH(int sh){
- this.minSH = sh;
- }
- private 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()){
- DragAdapter adapter = (DragAdapter)getAdapter();
- adapter.reFlag();
- }
- // DragAdapter adapter = (DragAdapter)getAdapter();
- // adapter.reFlag();
- }
- private void actDown(){
- int tempPosition = pointToPosition(this.middleX, this.middleY);
- if (tempPosition != AdapterView.INVALID_POSITION) {
- this.dragPosition = tempPosition;
- }
- dragPositionChanged();
- }
- private void actUp(){
- int tempPosition = pointToPosition(this.middleX, this.middleY);
- if (tempPosition != AdapterView.INVALID_POSITION) {
- this.dragPosition = tempPosition;
- }
- dragPositionChanged();
- }
- class RefreshHandler extends Handler {
- boolean isUp;
- public RefreshHandler(Looper looper, boolean isUp){
- super(looper);
- this.isUp = isUp;
- }
- public RefreshHandler(Looper l) {
- super(l);
- }
- public void handleMessage(Message msg){
- if (GragGridView.this.isDrag) {
- if (this.isUp)
- GragGridView.this.actUp();
- else {
- GragGridView.this.actDown();
- }
- sleep(GragGridView.this.scrollDelayMillis);
- }
- }
- public void sleep(long delayMillis) {
- sendMessageDelayed(obtainMessage(0), delayMillis);
- }
- }
- }
2、在包com.cn.daming.draggridview中,有两个类---->
2.1、GragGridViewAppActivity.java入口类中的代码:
- <span style="color:#000000;FONT-SIZE: 16px">package com.cn.daming.draggridview;
- import java.util.ArrayList;
- import android.app.Activity;
- import android.content.Context;
- import android.graphics.Color;
- import android.graphics.drawable.Drawable;
- import android.os.Bundle;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.ImageView;
- import android.widget.TextView;
- import com.cn.daming.adapter.DragAdapter;
- import com.cn.daming.adapter.DragMessage;
- import com.cn.daming.adapter.GragGridView;
- public class GragGridViewAppActivity extends Activity {
- private MyAdapter myAdapter;
- private ArrayList<DragMessage> mlist = new ArrayList<DragMessage>();
- private GragGridView mGridView;
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.drag_grid_activity);
- initDate();
- mGridView = (GragGridView)findViewById(R.id.drag_grid);
- myAdapter = new MyAdapter(this, mlist);
- mGridView.setAdapter(myAdapter);
- //设置触发拖动的区域,用一个ImageView来设置,这个必须设置
- mGridView.setDragImageId(R.id.grag_grid_item_view);
- //以下这些都做了相应的处理,不设置没关系,而且效果也不错
- //设置拖动浮项的背景色
- // mListView.setDragColor(Color.RED);
- //设置滚动的最大像素
- // mListView.setMaxSH(sh);
- //设置滚动的最小像素
- // mListView.setMinSH(sh);
- //设置滚动区的高度(2*height应该小于ListView自己的高度)
- // mListView.setMoveHeight(height);
- }
- private void initDate(){
- for (int i = 1; i <= 100; i++) {
- MyMessage msg = new MyMessage();
- String str = "DM_" + i;
- msg.msg = str;
- mlist.add(msg);
- }
- }
- class MyAdapter extends DragAdapter{
- Drawable background;
- public MyAdapter(Context mContext, ArrayList<DragMessage> mlist) {
- super(mContext, mlist);
- }
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- View view = convertView;
- ViewHolder holder = null;
- if (view == null) {
- view = LayoutInflater.from(mContext).inflate(
- R.layout.drag_grid_item, null);
- holder = new ViewHolder();
- holder.tv = (TextView) view
- .findViewById(R.id.drag_grid_item_text);
- holder.iv = (ImageView) view
- .findViewById(R.id.drag_grid_item_image);
- view.setTag(holder);
- } else {
- holder = (ViewHolder) view.getTag();
- }
- holder.tv.setText(((MyMessage)getItem(position)).msg);
- holder.iv.setBackgroundResource(R.drawable.title2);
- if(background == null){
- background = view.getBackground();}
- if(getItem(position).flag == DragMessage.MOVE_FLAG){
- view.setBackgroundColor(Color.GRAY);
- }
- else{
- view.setBackgroundDrawable(background);
- }
- return view;
- }
- }
- private class ViewHolder {
- TextView tv;
- ImageView iv;
- }
- }</span>
2.2、MyMessage.java中的代码:
- <span style="color:#000000;FONT-SIZE: 16px">package com.cn.daming.draggridview;
- import com.cn.daming.adapter.DragMessage;
- public class MyMessage extends DragMessage{
- public String msg;
- }
- </span>
3、布局文件layout有两个----->
3.1、drag_grid_activity.xml中的代码如下:
- <span style="color:#000000;FONT-SIZE: 16px"><?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical" >
- <com.cn.daming.adapter.GragGridView
- android:id="@+id/drag_grid"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:numColumns="auto_fit"
- android:columnWidth="70dp"
- android:stretchMode="columnWidth"
- android:gravity="center"
- android:layout_gravity="center"
- android:cacheColorHint="#00000000"/>
- </LinearLayout></span>
3.2、drag_grid_item.xml中的代码如下:
- <span style="color:#000000;FONT-SIZE: 16px"><?xml version="1.0" encoding="utf-8"?>
- <!-- 一定要使用相对布局 -->
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:background="#FFFFFF"
- android:id="@+id/grag_grid_item_view"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent">
- <TextView
- android:id="@+id/drag_grid_item_text"
- android:layout_width="wrap_content"
- android:layout_height="50dp"
- android:paddingLeft="5dip"
- android:gravity="center"
- android:textColor="#ffff00ff"
- android:layout_below="@+id/drag_grid_item_image"
- android:capitalize="none"
- />
- <ImageView
- android:id="@+id/drag_grid_item_image"
- android:layout_width="50dp"
- android:layout_height="50dp"
- android:scaleType="center"
- />
- </RelativeLayout> </span>
有问题的可以留言,欢迎大家来讨论研究,分享知识,共同进步!
以下是我在开发中遇到问题的参考资料:
http://www.cnblogs.com/qianxudetianxia/archive/2011/06/19/2084886.html
http://lipeng88213.iteye.com/blog/1099621
http://hi.baidu.com/jwq359699768/blog/item/f2caee8741e71131c75cc369.html
源代码下载地址:http://download.csdn.net/detail/wdaming1986/4207350
Android中GridView拖拽的效果的更多相关文章
- Android中GridView拖拽的效果【android进化三十六】
最 近看到联想,摩托罗拉等,手机launcher中有个效果,进入mainmenu后,里面的应用程序的图标可以拖来拖去,所以我也参照网上给的代码,写了 一个例子.还是很有趣的,实现的流畅度没有人家的 ...
- Android中GridView的按下效果及selector的使用
gridView.setSelector(new ColorDrawable(Color.TRANSPARENT)); 详细说明:http://blog.csdn.net/songzhiyong112 ...
- android ListView和GridView拖拽移位具体实现及拓展
关于ListView拖拽移动位置,想必大家并不陌生,比较不错的软件都用到如此功能了.如:搜狐,网易,百度等,但是相比来说还是百度的用户体验较好,不偏心了,下面看几个示例: 首 ...
- ToolStrip控件左右拖拽移动效果实现
1.主窗体下部添加一个Panel乘放ToolStrip控件以实现ToolStrip在窗体下部定位.2.当ToolStrip控件中子控件超出屏幕时,拖动控件可以实现滑动效果.拖动到控件边缘距窗体边缘1/ ...
- reactnative实现qq聊天消息气泡拖拽消失效果
前言(可跳过) 我在开发自己的APP时遇到了一个类似于qq聊天消息气泡拖拽消息的需求,因为在网上没有找到相关的组件,所以自己动手实现了一下 需求:对聊天消息气泡拖拽到一定长度松开时该气泡会消失(可自行 ...
- Asp.net中存储过程拖拽至dbml文件中,提示无法获得返回值
Asp.net中存储过程拖拽至dbml文件中,提示无法获得返回值,去属性表中设置这时候会提示你去属性表中更改返回类型. 其实存储过程返回的也是一张表,只不过有时候存储过程有点复杂或者写法不规范的话不能 ...
- Android中GridView通过自定义适配器(未优化)实现图文视图排列
Android中GridView组件用来以网格方式排列视图,与矩阵类似,当屏幕上有很多元素(文字.图片或其他元素)需要显示时,可以使用该组件.下面我们通过代码实现如下图例(为了方便截图,将事件处理(土 ...
- iOS开发拓展篇—xib中关于拖拽手势的潜在错误
iOS开发拓展篇—xib中关于拖拽手势的潜在错误 一.错误说明 自定义一个用来封装工具条的类 搭建xib,并添加一个拖拽的手势. 主控制器的代码:加载工具条 封装工具条以及手势拖拽的监听事件 此时运行 ...
- react实现的点击拖拽元素效果
之前用vue做日程管理组件的时候,用到了点击拖拽的效果,即点击元素,鼠标移动到哪里,元素移动到哪里,鼠标松开,拖拽停止,现在在弄react,于是也在想实现这个效果,经过一番折腾,效果出来了,代码如下: ...
随机推荐
- 哈希表(hashtable)的javascript简单实现
javascript中没有像c#,java那样的哈希表(hashtable)的实现.在js中,object属性的实现就是hash表,因此只要在object上封装点方法,简单的使用obejct管理属性的 ...
- vscode编写插件详细过程
前言 之前编写了一个vscode插件用vscode写博客和发布,然后有园友要求写一篇来介绍如何开发一个vscode扩展插件,或者说介绍开发这个插件的过程.然而文章还没有写,园子里面已经有人发布一个文章 ...
- 黑马程序员——vim编辑器的使用
------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 一.基本操作 1.从命令提示符进入vim编辑器: vim filename <ENTE ...
- BZOJ 2226 LCMSum
Description Given \(n\), calculate the sum \(LCM(1,n) + LCM(2,n) + \cdots + LCM(n,n)\), where \(LCM( ...
- 自定义元素–为你的HTML代码定义新元素
注意:这篇文章介绍的 API 尚未完全标准化,并且仍在变动中,在项目中使用这些实验性 API 时请务必谨慎. 引言 现在的 web 严重缺乏表达能力.你只要瞧一眼“现代”的 web 应用,比如 GMa ...
- RabbitMQ安装简单过程
找到一本ACTION IN RABBITMQ,仔细看.现在先安装起来.. 参考主要的URL,包括安装,用户管理,权限管理.我用的都是最新版本. http://my.oschina.net/indest ...
- 使用Git将本地代码上传到GitHub
#1注册GitHub账号 *1)到https://github.com/注册GitHub账号 #2在GitHub上建立GitHub仓库 *1)登录后点击右下方的"new repository ...
- 创办支持多种屏幕尺寸的Android应用
创建支持多种屏幕尺寸的Android应用 Android涉及各种各样的支持不同屏幕尺寸和密度的设备.对于应用程序,Android系统通过设备和句柄提供了统一的开发环境,大部分工作是校正每一个应用程序的 ...
- 【HDOJ】3308 LCIS
线段树,题目感觉比较难,看别人思路做的.还得继续练这个专题. #include <iostream> #include <cstdio> #include <cstrin ...
- 【Mongous】write after end
执行1(---) 执行2(----) 完成1(POST) 执行3(---)