Egret 长按拖拽实现交换图片位置

开发中经常遇到拖拽交换图片列表中的图片位置,决定写个简单通用的demo以便不时之需。我的项目是Egret引擎做的,因为demo是项目中写好简化出来的,所以demo也是Egret实现的,如果是其他语言,具体代码不同,但思路上应该大同小异。

先上实现效果:

功能描述:

对显示的图片列表(这里用的是2*4的图片列表),用户可以通过长按单个图片,然后拖拽与其他图片交换位置,并且其他图片位置顺位移动。当然用户也可以通过点击单个图片对图片编辑。

实现思路:

1.长按与点击的区分。可以启动计时器,判断当前点击是否是长按(比如触摸达到一秒以上即认为是长按,否则为一般点击)。

2.拖拽与交换位置。获取当前拖拽的图片的位置,判断是否达到与另一图片交换位置的临界条件,如果达到交换条件,则交换图片位置,并更新其他图片位置。

具体实现关键代码:

代码也比较简单,主要包含两个文件,一个是AvatarList.ts,为头像列表类;另一个是单个头像item:AvatarListItem。实现逻辑都在AvatarList.ts中。

对每个头像item设置点击监听,分别是开始触摸,图片移动和结束触摸:

avatarListItem.addEventListener(egret.TouchEvent.TOUCH_BEGIN,this.avatarItemTouchBeginHandler, this);//开始点击头像
avatarListItem.addEventListener(egret.TouchEvent.TOUCH_MOVE,this.avatarItemTouchMoveHandler, this);//拖拽头像
avatarListItem.addEventListener(egret.TouchEvent.TOUCH_END, this.avatarItemTouchEndHandler, this);//结束点击头像

开始触摸响应方法里要记录触摸点与图片锚点的坐标差,并启动倒计时以判断是否是长按:

//开始点击头像
private avatarItemTouchBeginHandler(e:egret.TouchEvent){
	//记录点击位置与图片锚点的坐标差
	let avatarListItem:AvatarListItem = <AvatarListItem>e.currentTarget;
	let point = this.gpAvatarList.globalToLocal(e.stageX, e.stageY);
	this._distance.x = point.x - avatarListItem.x;
	this._distance.y = point.y - avatarListItem.y;

	this.avatarTouchTimer.start();
	this.avatarTouchTimer.addEventListener(egret.TimerEvent.TIMER,this.timerCountEnd,this);
	this.avatarTouchFlg = 1;//开始点击
}

接下来是图片移动的响应方法,这里要判断是否是长按拖拽,触摸时间不到1000ms则不能拖拽:

//拖拽头像
private avatarItemTouchMoveHandler(e:egret.TouchEvent){
    if(this.avatarTouchFlg == 2){//如果是长按则可以移动,否则不能移动
        let avatarListItem:AvatarListItem = <AvatarListItem>e.currentTarget;
        this.gpAvatarList.setChildIndex(avatarListItem, this.gpAvatarList.numChildren - 1);//将该图片置顶
        // 从舞台(全局)坐标转换为显示对象的(本地)坐标
        let point = this.gpAvatarList.globalToLocal(e.stageX, e.stageY);

        //移动图片到点击位置
        avatarListItem.x = point.x - this._distance.x;
        avatarListItem.y = point.y - this._distance.y;

        //刷新图片位置
        this.refreshAvatarList(avatarListItem,point);
    }
}

再触摸结束时,判断是长按还是普通点击,并分别处理:

//结束点击头像
private avatarItemTouchEndHandler(e:egret.TouchEvent){
    if(this.avatarTouchFlg == 1){//点击
        //TODO 打开编辑头像小弹框

    }else if(this.avatarTouchFlg == 2){//长按,拖动结束
        //快速拖动可能会出现错位情况,所以刷新校正全部图片位置
        for(let i=0; i<this.avatarArray.length; i++){
            let avatarListItem:AvatarListItem = this.avatarArray[i];
            let index = avatarListItem.AvatarIndex;
            avatarListItem.x = this.position_Array[index].x;
            avatarListItem.y = this.position_Array[index].y;
        }
    }
    this.avatarTouchFlg = 0;//设置点击标志
}

对长按还是普通点击的判断标识的设置,是在倒计时结束的响应方法里,这里设置触摸不小于1000ms即为长按,否则为普通点击:

//倒计时结束
private timerCountEnd(e:Event){
    if(this.avatarTouchFlg == 1){//如果点击了并且没有结束点击,则表示是长按
        this.avatarTouchFlg = 2;//长按
    }
    //重置计时器
    this.avatarTouchTimer.reset();
		 
 this.avatarTouchTimer.removeEventListener(egret.TimerEvent.TIMER,this.timerCountEnd,this);
}

刷新(交换)头像位置的方法也比较简单,我这里设置的是交换临界点是两张图片单向重叠达到图片宽度(或高度)的一半,就交换位置,并刷新其他图片位置。方法如下,具体代码就不贴了,后边我会附上完整demo:

//刷新头像位置
private refreshAvatarList(targetItem:AvatarListItem, currentPosition:egret.Point)

关键代码就是以上部分,其他的看注释应该都能明白。完整demo已经上传到个人资源,如果需要可以自行下载。

(注:不知道为什么,csdn的代码粘贴板不支持TS的代码格式,粘贴进去缩进格式简直不能看,只能一行一行手动调整,所以大段代码我没有贴进去,大家可以下载完整demo查看。还请见谅!)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值