当前位置: 首页 > news >正文

鸿蒙之Grid实现拖动自定义排序特效

涉及的事件及组件

1、Grid组件

网格容器,由“行”和“列”分割的单元格所组成,通过指定“项目”所在的单元格做出各种各样的布局。仅支持GridItem子组件,支持渲染控制类型(if/else、ForEach、LazyForEach和Repeat)

2、事件

onItemDragStart8+

onItemDragStart(event: (event: ItemDragInfo, itemIndex: number) => (() => any) | void)

开始拖拽网格元素时触发。返回void表示不能拖拽。

手指长按GridItem时触发该事件。

由于拖拽检测也需要长按,且事件处理机制优先触发子组件事件,GridItem上绑定LongPressGesture时无法触发拖拽。如有长按和拖拽同时使用的需求可以使用通用拖拽事件。

参数名类型必填说明
eventItemDragInfo拖拽点的信息。
itemIndexnumber拖拽离开的网格元素索引值。

onItemDrop8+

onItemDrop(event: (event: ItemDragInfo, itemIndex: number, insertIndex: number, isSuccess: boolean) => void)

绑定该事件的网格元素可作为拖拽释放目标,当在网格元素内停止拖拽时触发

参数:

参数名类型必填说明
eventItemDragInfo拖拽点的信息。
itemIndexnumber拖拽起始位置。
insertIndexnumber拖拽插入位置。
isSuccessboolean是否成功释放

代码:

import {  promptAction } from '@kit.ArkUI';// 定义车门车控列表数据类型
interface IVehicleDoor{title:stringicon:ResourceStr
}
//注意要用模拟器,用预览器将会出现空白效果
@Entry
@Component
struct Index {// 存储渲染数据列表的数组@State VehicleDoorArr:IVehicleDoor[] = []// 当前移动的Item索引@State CurrentIndex:number = -1// 拖动时显示的数据@State MoveItem:IVehicleDoor = {title:'',icon:''}// 拖动时放大倍数@State ScaleXY:ScaleOptions = {x:1,y:1}// 是否超出范围@State isExtendGridArea:boolean = false@State isPress:boolean = false//是否按压aboutToAppear() {// 列表的数据let list:IVehicleDoor[] =  [{title:'远程启动1',icon:$r("app.media.icon_nor01")},{title:'远程启动2',icon:$r("app.media.icon_nor01")},{title:'远程启动3',icon:$r("app.media.icon_nor01")},{title:'远程启动4',icon:$r("app.media.icon_nor01")},{title:'远程启动5',icon:$r("app.media.icon_nor01")},{title:'远程启动6',icon:$r("app.media.icon_nor01")},{title:'远程启动7',icon:$r("app.media.icon_nor01")},]if(this.VehicleDoorArr.length==0){list.forEach((item:IVehicleDoor,index:number)=>{this.VehicleDoorArr.push(item)})}}changeIndex(itemIndex: number, inertIndex: number) {// 交换数组位置let temp = this.VehicleDoorArr[itemIndex];this.VehicleDoorArr[itemIndex] = this.VehicleDoorArr[inertIndex];this.VehicleDoorArr[inertIndex] = temp;}//设置拖拽过程中显示的图片。@BuilderpixelMapBuilder() {VehicleDoorItem({VehicleDoorItem:this.MoveItem})}build() {Column() {Row(){Divider().strokeWidth(0.5).width(95)Text('长按可拖动顺序').width(112).height(24).fontSize('16fp').fontWeight(400).textAlign(TextAlign.Center).fontFamily('PingFang SC').margin({left:16.5,right:16.5})Divider().strokeWidth(0.5).width(95)}.width('100%').margin({top:24,bottom:24}).justifyContent(FlexAlign.Center).alignItems(VerticalAlign.Center)// 车控列表项目Grid(){ForEach(this.VehicleDoorArr,(item:IVehicleDoor,index:number)=>{GridItem(){VehicleDoorItem({VehicleDoorItem:(item?item:this.MoveItem)})}.scale(this.CurrentIndex === index?this.ScaleXY:{x:1,y:1}).onTouch((event: TouchEvent) => {// 按下时if(event.type === TouchType.Down){this.MoveItem = this.VehicleDoorArr[index]this.CurrentIndex = indexthis.isPress = truesetTimeout(()=>{if(this.isPress){animateTo({duration:100, curve:Curve.Linear,onFinish:()=>{// this.ScaleXY = {x:1,y:1}}},()=>{this.ScaleXY = {x:1.3,y:1.3}})}},700)}// 松开时if (event.type === TouchType.Up) {this.isPress = falseanimateTo({duration:400, curve:Curve.EaseIn,onFinish:()=>{}},()=>{this.ScaleXY = {x:1,y:1}})}})})}.columnsTemplate('1fr 1fr 1fr 1fr').rowsGap(31).columnsGap(37).width('100%').height(300).padding({left:20,right:20}).clip(true)//超出容器范围时剪裁.supportAnimation(true)//开启GridItem支持拖拽动画.editMode(true) // 设置Grid是否进入编辑模式,进入编辑模式可以拖拽Grid组件内部GridItem// .onItemDragLeave(()=>{//   // 拖拽出组件范围//   this.isExtendGridArea = true//   promptAction.showToast({message: '离开了'})// })// .onItemDragEnter(()=>{//   promptAction.showToast({message: '进入了'})//   // 重新进入组件//   this.isExtendGridArea = false// }).onItemDragStart((event: ItemDragInfo, itemIndex: number) => {// 第一次拖拽此事件绑定的组件时,触发回调。(开始拖动时触发)this.CurrentIndex = itemIndexthis.MoveItem = this.VehicleDoorArr[itemIndex]return this.pixelMapBuilder(); //设置拖拽过程中显示的图片。})// 绑定此事件的组件可作为拖拽释放目标,当在本组件范围内停止拖拽行为时,触发回调。.onItemDrop((event: ItemDragInfo, itemIndex: number, insertIndex: number, isSuccess: boolean) => {// itemIndex拖拽起始位置,insertIndex拖拽插入位置,// isSuccess是否成功释放// promptAction.showToast({message:'insertIndex'+insertIndex+'itemIndex'+itemIndex})if(insertIndex===-1){//如果insertIndex的值为-1,代表插入位置出现错误insertIndex = this.CurrentIndex}// AlertDialog.show({message:'insertIndex2'+insertIndex+'itemIndex2'+itemIndex})if(insertIndex>this.VehicleDoorArr.length||!isSuccess){return}this.changeIndex(itemIndex,insertIndex)promptAction.showToast({message:'切换成功'+insertIndex+'insertIndex'+'itemIndex'+itemIndex})this.isPress?this.ScaleXY={x:1.3,y:1.3}:this.ScaleXY={x:1,y:1}})Blank()//   完成按钮Row(){Button('完成').width(240).height(44).backgroundColor(Color.Transparent).border({width:1}).fontColor(Color.Black).padding(0).fontFamily('PingFang SC').fontWeight(400).fontSize('16fp').onClick(()=>{//   todo:接口提交保存数据})}.margin({bottom:54}).width('100%').justifyContent(FlexAlign.Center).zIndex(99)}.height('100%').width('100%').backgroundColor('rgba(248, 248, 248, 1)').expandSafeArea([SafeAreaType.SYSTEM,SafeAreaType.KEYBOARD], [ SafeAreaEdge.BOTTOM])}
}
// GridItem子列表项
@Component
export struct VehicleDoorItem{@Prop VehicleDoorItem:IVehicleDoorbuild() {Column(){Column(){Image(this.VehicleDoorItem.icon).width(24).aspectRatio(1)}.height(56).width(56).borderRadius(56).justifyContent(FlexAlign.Center).backgroundColor(Color.White)// .draggable(true)//是否支持拖拽Text(this.VehicleDoorItem.title).height(17).fontSize('12fp').textAlign(TextAlign.Center).fontFamily('PingFang SC').fontWeight(400).margin({top:6})}}
}

效果:

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 决策树(Decision Tree)
  • 培训第十三天(DNS逆向解析与主从服务、ntp时间服务器)
  • 【接口自动化_08课_Pytest+Yaml+Allure框架】
  • 从统计学、到机器学习和ChatGPT
  • 数据结构第三讲:单链表的实现
  • GitLab添加TortoiseGIT生成SSH Key
  • Java 中如何执行命令行方法
  • 初识godot游戏引擎并安装
  • JAVA基础知识4(static、继承)
  • Spring中存储Bean的相关注解及用法
  • 【C++】类和对象之继承
  • 数组算法--二分查找
  • php 做一个mqtt按钮,发布触发信号
  • Unity UGUI 之 Input Field
  • 深入浅出WebRTC—Pacer
  • 【翻译】Mashape是如何管理15000个API和微服务的(三)
  • 【许晓笛】 EOS 智能合约案例解析(3)
  • Angular6错误 Service: No provider for Renderer2
  • ERLANG 网工修炼笔记 ---- UDP
  • Fabric架构演变之路
  • LeetCode刷题——29. Divide Two Integers(Part 1靠自己)
  • LeetCode算法系列_0891_子序列宽度之和
  • php ci框架整合银盛支付
  • python 学习笔记 - Queue Pipes,进程间通讯
  • Quartz实现数据同步 | 从0开始构建SpringCloud微服务(3)
  • React系列之 Redux 架构模式
  • 关键词挖掘技术哪家强(一)基于node.js技术开发一个关键字查询工具
  • 前端相关框架总和
  • 山寨一个 Promise
  • 通过几道题目学习二叉搜索树
  • 职业生涯 一个六年开发经验的女程序员的心声。
  • puppet连载22:define用法
  • #[Composer学习笔记]Part1:安装composer并通过composer创建一个项目
  • (1)Android开发优化---------UI优化
  • (6)【Python/机器学习/深度学习】Machine-Learning模型与算法应用—使用Adaboost建模及工作环境下的数据分析整理
  • (7)STL算法之交换赋值
  • (CVPRW,2024)可学习的提示:遥感领域小样本语义分割
  • (ISPRS,2021)具有遥感知识图谱的鲁棒深度对齐网络用于零样本和广义零样本遥感图像场景分类
  • (k8s)Kubernetes 从0到1容器编排之旅
  • (pt可视化)利用torch的make_grid进行张量可视化
  • (Qt) 默认QtWidget应用包含什么?
  • (算法)硬币问题
  • (一)UDP基本编程步骤
  • (转)PlayerPrefs在Windows下存到哪里去了?
  • (转载)从 Java 代码到 Java 堆
  • ./include/caffe/util/cudnn.hpp: In function ‘const char* cudnnGetErrorString(cudnnStatus_t)’: ./incl
  • ./mysql.server: 没有那个文件或目录_Linux下安装MySQL出现“ls: /var/lib/mysql/*.pid: 没有那个文件或目录”...
  • .cfg\.dat\.mak(持续补充)
  • .NET Framework 4.6.2改进了WPF和安全性
  • .NET Framework与.NET Framework SDK有什么不同?
  • .Net Remoting常用部署结构
  • .NET 给NuGet包添加Readme
  • .NET:自动将请求参数绑定到ASPX、ASHX和MVC(菜鸟必看)
  • .netcore如何运行环境安装到Linux服务器
  • .NET业务框架的构建