自定义ListView实现拖拽ListItem项交换位置(附源码)

论坛 期权论坛 脚本     
niminba   2021-5-16 20:40   216   0
写在前面的话
上一篇实现了通过布局泵拿到不同布局为listitem布局,然后实现联系人的ListView,这一章要做的是拖拽ListView的Item项,本章原理是在上一篇博客基础之上的,上一篇博客:自定义Adapter并通过布局泵LayoutInflater抓取layout模板编辑每一个item

实现效果图
 

说明
首先我们看到的上面这张图就是实现的效果图了。拖动之后数据项完成交换位置。

功能剖析
我们看到做的这个效果是一个拖拽ListView的Item项位置的功能,在布局方面还是用基于布局泵LayoutInflater来从不同的Layout模板拿到不同的布局然后将view返回。关于布局这一点的知识在上一篇有详细说明,文章开头已经说明,OK,下面我们来剖析一下这个拖动效果的实现吧,下面的文章将会以方法执行的顺序来给出各个方法的代码。然后依次剖析每个方法的作用。

方法执行顺序
[DragView] -> [初始化ListViewContext,和触发move事件的最小距离变量]
[onInterceptTouchEvent] -> [初始化拖动的变量]
[startDrag] -> [准备拖动的影像、window等变量]
[stopDrag] -> [判断重置拖动的影像]
[startDrag] -> [准备拖动的影像、window等变量]
[onTouchEvent] -> [判断点击事件、根据动作做不同操作,或重新绘制Move影响,或者Stop停止拖动。交换数据,也就是下面的这两个方法]
[onDrag] -> [实现滚动的动作]
[onDrop] -> [实现数据item位置切换]
注意
上面的方法执行顺序只是大概逻辑,这其中还有判断和方法中调用其他方法,所以方法的调用是多次的,大家凑合看一下方法的大体功能吧,需要注意的是我们重写的onTouchEvent是要一直不断的监听我们的按键的,如果为Move的话也就是会一直不断的去调用onDrag方法去实现滚动的动作,在此我做了测试,给大家看一下打印的日志如下:
 
我们看到move日志被执行了多次。说明我们在拖动的时候一直在执行这个方法。下面我会给大家自定义ListView的代码,代码中注释量很大,可读性很高,推荐大家参考上面我给出的方法运行顺序去理解,最后我将给出运行源码。
复制代码 代码如下:

package com.example.draglistview;
import com.example.draglistview.MainActivity.DragListAdapter;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.PixelFormat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.Toast;
public class DragView extends ListView{
private ImageView imageView; //被拖动的图片
private int scaledTouchSlop; //判断拖动的距离

private int dragSrcPosition; //手指在touch事件触摸时候的原始位置
private int dragPosition; //手指拖动列表项时候的位置

private int dragPoint; //手指点击位置在当前数据项item中的位置,只有Y坐标
private int dragOffset; //当前视图listview在屏幕中的位置,只有Y坐标

private int upScrollBounce; //向上滑动的边界
private int downScrollBounce; //拖动的时候向下滑动的边界

private WindowManager windowManager = null; //窗口管理类
//窗口参数类
private WindowManager.LayoutParams layoutParams = null;



//注意该View如果在Layout xml 注册使用的话必须使用下面的这个构造进行初始化
public DragView(Context context, AttributeSet attrs) {
super(context, attrs);
//触发移动事件的最小距离
scaledTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
}
//重写于absListView
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {

if(ev.getAction() == MotionEvent.ACTION_DOWN){
//获取的该touch事件的x坐标和y坐标,该坐标是相对于组件的左上角的位置
int x = (int) ev.getX();
int y = (int) ev.getY();
//赋值手指点击时候的开始坐标
dragSrcPosition = dragPosition = this.pointToPosition(x, y);
//如果点击在列表之外,也就是不允许的位置
if(dragPosition == AdapterView.INVALID_POSITION){
//直
分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:1060120
帖子:212021
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP