




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
【移动应用开发技术】Android如何实现可拖拽的GridView效果长按可拖拽删除数据源
在下给大家分享一下Android如何实现可拖拽的GridView效果长按可拖拽删除数据源,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!Android可拖拽的GridView效果实现,长按可拖拽和item实时交换简单修改,完成自己想要的功能:长按,移到垃圾桶,删除数据。主要思路是:1.获取到用户长按的操作2.获取按下的图片的bitmap以及移动的时候动态刷新镜像3action_up的时候判断镜像的位置,进入是否删除逻辑自定义控件package
com.leafact.GridView;
import
android.app.Activity;
import
android.content.Context;
import
android.graphics.Bitmap;
import
android.graphics.PixelFormat;
import
android.graphics.Rect;
import
android.os.Handler;
import
android.os.Vibrator;
import
android.util.AttributeSet;
import
android.view.Gravity;
import
android.view.MotionEvent;
import
android.view.View;
import
android.view.WindowManager;
import
android.widget.AdapterView;
import
android.widget.GridView;
import
android.widget.ImageView;
import
android.widget.Toast;
/**
*
长按能选中item的,丢入垃圾箱的gridView
*
*
@author
leafact
*
*/
public
class
MoveGridView
extends
GridView
{
private
WindowManager
mWindowManager;
/**
*
item镜像的布局参数
*/
private
WindowManager.LayoutParams
mWindowLayoutParams;
/**
*
震动器
*/
private
Vibrator
mVibrator;
//
震动的时间,默认为100ms
private
long
vibratorMs
=
100;
//
设置长按时间为1秒
private
long
responseMS
=
1000;
private
static
boolean
isMove
=
false;
//
按下去的x,y
private
int
mDownX
=
0;
private
int
mDownY
=
0;
//
移动的时候的x,y
private
int
mMoveX
=
0;
private
int
mMoveY
=
0;
//
抬起的x,y
private
int
mUpX
=
0;
private
int
mUpY
=
0;
private
int
mPoint2ItemTop;
private
int
mPoint2ItemLeft;
private
int
mOffset2Top;
private
int
mOffset2Left;
/**
*
状态栏的高度
*/
private
int
mStatusHeight;
public
MoveGridView(Context
context,
AttributeSet
attrs)
{
super(context,
attrs);
mVibrator
=
(Vibrator)
context
.getSystemService(Context.VIBRATOR_SERVICE);
mWindowManager
=
(WindowManager)
context
.getSystemService(Context.WINDOW_SERVICE);
mStatusHeight
=
getStatusHeight(context);
//
获取状态栏的高度
}
//
要移动的item的位置,默认为INVALID_POSITION=-1
private
int
mMovePosition
=
INVALID_POSITION;
/**
*
刚开始拖拽的item对应的View
*/
private
View
mStartMoveItemView
=
null;
private
ImageView
mMoveImageView
=
null;
private
Bitmap
mMoveBitmap;
private
Handler
mHandler
=
new
Handler();
//
判断是否能开始移动元素
private
Runnable
mLongClickRunnable
=
new
Runnable()
{
@Override
public
void
run()
{
isMove
=
true;
mVibrator.vibrate(vibratorMs);
//
根据我们按下的点显示item镜像
createDragImage(mMoveBitmap,
mDownX,
mDownY);
}
};
@Override
public
boolean
onTouchEvent(MotionEvent
ev)
{
switch
(ev.getAction())
{
case
MotionEvent.ACTION_DOWN:
mDownX
=
(int)
ev.getX();
mDownY
=
(int)
ev.getY();
System.out.println("ACTION_DOWN");
//
根据按下的X,Y坐标获取所点击item的position
mMovePosition
=
pointToPosition(mDownX,
mDownY);
//
如果选中的为非法的位置。则不处理消息
if
(mMovePosition
==
AdapterView.INVALID_POSITION)
{
break;
}
mHandler.postDelayed(mLongClickRunnable,
responseMS);
mStartMoveItemView
=
getChildAt(mMovePosition
-
getFirstVisiblePosition());
mPoint2ItemTop
=
mDownY
-
mStartMoveItemView.getTop();
mPoint2ItemLeft
=
mDownX
-
mStartMoveItemView.getLeft();
mOffset2Top
=
(int)
(ev.getRawY()
-
mDownY);
mOffset2Left
=
(int)
(ev.getRawX()
-
mDownX);
//
开启mMoveItemView绘图缓存
mStartMoveItemView.setDrawingCacheEnabled(true);
//
获取mMoveItemView在缓存中的Bitmap对象
mMoveBitmap
=
Bitmap.createBitmap(mStartMoveItemView
.getDrawingCache());
//
这一步很关键,释放绘图缓存,避免出现重复的镜像
mStartMoveItemView.destroyDrawingCache();
break;
case
MotionEvent.ACTION_MOVE:
mMoveX
=
(int)
ev.getX();
mMoveY
=
(int)
ev.getY();
//
如果我们在按下的item上面移动,只要不超过item的边界我们就不移除mRunnable
//
依然能监听到longClick
if
(!isTouchInItem(mStartMoveItemView,
mMoveX,
mMoveY))
{
mHandler.removeCallbacks(mLongClickRunnable);
}
//
//禁止Gridview侧边进行滑动,移动的时候不许发生侧滑事件
if
(isMove)
{
onDragItem(mMoveX,
mMoveY);
return
true;
}
break;
case
MotionEvent.ACTION_UP:
mUpX
=
(int)
ev.getX();
mUpY
=
(int)
ev.getY();
mHandler.removeCallbacks(mLongClickRunnable);
if(isMove){
deleteIfNeed();
}
removeDragImage();
isMove
=
false;
break;
default:
break;
}
return
super.onTouchEvent(ev);
}
/**
*
判断是否要删除,满足条件删除
*/
private
void
deleteIfNeed()
{
int
y
=
mUpY
-
mPoint2ItemTop
+
mOffset2Top
-
mStatusHeight;
if(y<50){
if(mUninstallListener!=null)
mUninstallListener.onUninstallListener(mMovePosition);
}
}
/**
*
是否点击在GridView的item上面
*
*
@param
itemView
*
@param
x
*
@param
y
*
@return
*/
private
boolean
isTouchInItem(View
dragView,
int
x,
int
y)
{
if
(dragView
==
null)
{
return
false;
}
int
leftOffset
=
dragView.getLeft();
int
topOffset
=
dragView.getTop();
if
(x
<
leftOffset
||
x
>
leftOffset
+
dragView.getWidth())
{
return
false;
}
if
(y
<
topOffset
||
y
>
topOffset
+
dragView.getHeight())
{
return
false;
}
return
true;
}
/**
*
创建拖动的镜像
*
*
@param
bitmap
*
@param
downX
*
按下的点相对父控件的X坐标
*
@param
downY
*
按下的点相对父控件的X坐标
*/
private
void
createDragImage(Bitmap
bitmap,
int
downX,
int
downY)
{
mWindowLayoutParams
=
new
WindowManager.LayoutParams();
mWindowLayoutParams.format
=
PixelFormat.TRANSLUCENT;
//
图片之外的其他地方透明
mWindowLayoutParams.gravity
=
Gravity.TOP
|
Gravity.LEFT;
mWindowLayoutParams.x
=
downX
-
mPoint2ItemLeft
+
mOffset2Left;
mWindowLayoutParams.y
=
downY
-
mPoint2ItemTop
+
mOffset2Top
-
mStatusHeight;
mWindowLayoutParams.alpha
=
0.55f;
//
透明度
mWindowLayoutParams.width
=
WindowManager.LayoutParams.WRAP_CONTENT;
mWindowLayoutParams.height
=
WindowManager.LayoutParams.WRAP_CONTENT;
mWindowLayoutParams.flags
=
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
|
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
mMoveImageView
=
new
ImageView(getContext());
mMoveImageView.setImageBitmap(bitmap);
mWindowManager.addView(mMoveImageView,
mWindowLayoutParams);
}
/**
*
从界面上面移动拖动镜像
*/
private
void
removeDragImage()
{
if
(mMoveImageView
!=
null)
{
mWindowManager.removeView(mMoveImageView);
mMoveImageView
=
null;
}
}
/**
*
拖动item,在里面实现了item镜像的位置更新,item的相互交换以及GridView的自行滚动
*
*
@param
x
*
@param
y
*/
private
void
onDragItem(int
moveX,
int
moveY)
{
mWindowLayoutParams.x
=
moveX
-
mPoint2ItemLeft
+
mOffset2Left;
mWindowLayoutParams.y
=
moveY
-
mPoint2ItemTop
+
mOffset2Top
-
mStatusHeight;
mWindowManager.updateViewLayout(mMoveImageView,
mWindowLayoutParams);
//
更新镜像的位置
}
/**
*
获取状态栏的高度
*
*
@param
context
*
@return
*/
private
static
int
getStatusHeight(Context
context)
{
int
statusHeight
=
0;
Rect
localRect
=
new
Rect();
((Activity)
context).getWindow().getDecorView()
.getWindowVisibleDisplayFrame(localRect);
statusHeight
=
localRect.top;
if
(0
==
statusHeight)
{
Class<?>
localClass;
try
{
localClass
=
Class.forName("ernal.R$dimen");
Object
localObject
=
localClass.newInstance();
int
i5
=
Integer.parseInt(localClass
.getField("status_bar_height").get(localObject)
.toString());
statusHeight
=
context.getResources().getDimensionPixelSize(i5);
}
catch
(Exception
e)
{
e.printStackTrace();
}
}
return
statusHeight;
}
/**
*
设置响应拖拽的毫秒数,默认是1000毫秒
*
*
@param
responseMS
*/
public
void
setResponseMS(long
responseMS)
{
this.responseMS
=
responseMS;
}
/**
*
设置震动时间的毫秒数,默认是1000毫秒
*
*
@param
responseMS
*/
public
void
setVibrator(long
vibratorMs)
{
this.vibratorMs
=
vibratorMs;
}
public
void
setOnUninstallListener(UninstallListener
l){
mUninstallListener=l;
};
private
UninstallListener
mUninstallListener;
}MainActivity.javapackage
com.example.gridviewmovedemo;
import
java.util.ArrayList;
import
java.util.HashMap;
import
android.app.Activity;
import
android.os.Bundle;
import
android.view.Menu;
import
android.view.View;
import
android.widget.AdapterView;
import
android.widget.AdapterView.OnItemLongClickListener;
import
android.widget.SimpleAdapter;
import
com.leafact.GridView.MoveGridView;
import
com.leafact.GridView.UninstallListener;
public
class
MainActivity
extends
Activity
{
private
MoveGridView
mMoveGridView;
@Override
protected
void
onCreate(Bundle
savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mMoveGridView
=
(MoveGridView)
findViewById(R.id.gridview);
final
ArrayList<HashMap<String,
Object>>
lstImageItem
=
new
ArrayList<HashMap<String,
Object>>();
for
(int
i
=
0;
i
<
10;
i++)
{
HashMap<String,
Object>
map
=
new
HashMap<String,
Object>();
map.put("ItemText",
"NO."
+
String.valueOf(i));//
按序号做ItemText
lstImageItem.add(map);
}
final
SimpleAdapter
saImageItems
=
new
SimpleAdapter(this,
lstImageItem,//
数据来源
R.layout.gridview_item,
//
动态数组与ImageItem对应的子项
new
String[]
{
"ItemText"
},
//
ImageItem的XML文件里面的一个ImageView,两个TextView
ID
new
int[]
{
R.id.ItemText
});
//
添加并且显示
mMoveGridView.setAdapter(saImageItems);
//监听到卸载删除数据
mMoveGridView.setOnUninstallListener(new
UninstallListener()
{
@Override
public
void
onUninstallListener(int
position)
{
lstImageItem.remove(position);
saImageItems.notifyDataSetChanged();
}
});
}
@Override
public
boolean
onCreateOptionsMenu(Menu
menu)
{
getMenuInflater().inflate(R.menu.main,
menu);
return
true;
}
}UninstallListener.javapackage
com.leafact.GridView;
public
interface
UninstallListener
{
void
onUninstallListener(int
position);
}activity_main.xml<LinearLayout
xmlns:android="/apk/res/android"
xmlns:tools="/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#fff"
android:orientation="vertical"
tools:co
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年黑龙江省齐齐哈尔市物理试题高考冲刺卷(七)含解析
- 株洲师范高等专科学校《多媒体出版》2023-2024学年第二学期期末试卷
- 安徽省定远县2024-2025学年初三一模(期末)英语试题含答案
- 重庆青年职业技术学院《网络管理与开发》2023-2024学年第二学期期末试卷
- 广东省东莞市重点中学2025届高考信息卷数学试题含解析
- 江苏省南京市江北新区2025届初三第二次物理试题模拟考试含解析
- 天津市静海县名校2024-2025学年高中毕业班第二次模拟(英语试题文)试卷含答案
- 2025年内蒙古海拉尔区市级名校初三第四次联考英语试题含答案
- 虎林市2024-2025学年小升初考试数学试卷含解析
- 贵州盛华职业学院《生物统计学》2023-2024学年第二学期期末试卷
- 2025年中医针灸学主治医师-中医针灸学考试题(附答案)
- 老年人安全用药与护理
- 黑色三分钟生死一瞬间第9、10部
- 适老化住宅改造服务行业深度调研及发展战略咨询报告
- 2025年郑州黄河护理职业学院单招职业技能测试题库及答案1套
- 2025年上半年甘肃省农垦集团限责任公司人才招聘380人易考易错模拟试题(共500题)试卷后附参考答案
- GB/T 45236-2025化工园区危险品运输车辆停车场建设规范
- 中考语文文学批注-病句表达欠妥(含答案)
- 新地基基础-基桩静荷载试验考试复习题库(含答案)
- 《致敬英雄》课件
- 2025年河南经贸职业学院单招职业技能测试题库完整
评论
0/150
提交评论