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

鸿蒙List组件通过拖拽改变排序

效果图和视频

效果是视频

鸿蒙

该组件具备以下核心特性:

  • 长按激活拖拽:长按列表项触发缩放高亮效果,进入可拖拽状态;
  • 实时位置交换:拖拽过程中,当 item 位移超过阈值时,自动与上下相邻项交换位置;
  • 动态视觉反馈:被拖拽项放大显示并提升层级,相邻项随拖拽距离产生缩放动画;
  • 交互开关控制:通过按钮可切换拖拽功能的启用 / 禁用状态,灵活适配业务场景。

代码如下

import { curves } from "@kit.ArkUI"@Entry
@Component
export struct Index {@State private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]@State dragItem: number = -1 // 当前拖拽的项目@State scaleItem: number = -1 // 当前缩放的项目@State neighborItem: number = -1 // 相邻项目@State neighborScale: number = -1 // 相邻项目的缩放比例private dragRefOffset: number = 0 // 拖拽参考偏移@State offsetX: number = 0 // 偏移量@State offsetY: number = 0private itemIntv: number = 120 // 项目间隔@State moveControls: boolean = false // 控制拖拽功能scaleSelect(item: number): number {if (this.scaleItem == item) {return 1.05} else if (this.neighborItem == item) {return this.neighborScale} else {return 1}}itemMove(index: number, newIndex: number): void {let tmp = this.arr.splice(index, 1)this.arr.splice(newIndex, 0, tmp[0])}build() {Stack() {Column() {Button('是否可以拖动:' + !this.moveControls).width(200).margin(20).onClick(() => {this.moveControls = !this.moveControls})List({ space: 20, initialIndex: 0 }) {ForEach(this.arr, (item: number) => {ListItem() {Text('' + item).width('100%').height(100).fontSize(16).textAlign(TextAlign.Center).borderRadius(10).backgroundColor(0xFFFFFF)// 通过状态变量scaleItem判断是否为组件添加阴影效果.shadow(this.scaleItem == item ? {radius: 70,color: '#15000000',offsetX: 0,offsetY: 0} : {radius: 0,// 阴影半径为0,相当于没有阴影color: '#15000000',offsetX: 0,offsetY: 0})// 设置锐利曲线动画,持续时间为300毫秒.animation({ curve: Curve.Sharp, duration: 300 })}.draggable(this.moveControls).margin({ left: 12, right: 12 }).scale({ x: this.scaleSelect(item), y: this.scaleSelect(item) })// 增加x轴、y轴缩放效果.zIndex(this.dragItem == item ? 1 : 0)// 设置组件的堆叠顺序,实现拖拽过程中被拖拽组件覆盖其他组件的效果.translate(this.dragItem == item ? { y: this.offsetY } : { y: 0 }).gesture(// 以下组合手势为顺序识别,当长按手势事件未正常触发时则不会触发拖动手势事件GestureGroup(GestureMode.Sequence,// 长按手势识别LongPressGesture({ repeat: true }).onAction((event?: GestureEvent) => { // 长按手势识别成功回调// 设置显示动画为阻尼曲线,持续时间为300毫秒animateTo({ curve: Curve.Friction, duration: 300 }, () => {this.scaleItem = item})})// 长按手势识别成功,最后一根手指抬起后触发回调.onActionEnd(() => {// 设置显示动画为阻尼曲线,持续时间为300毫秒animateTo({ curve: Curve.Friction, duration: 300 }, () => {this.scaleItem = -1})}),// 设置滑动手势事件,任意滑动方向都能够触发事件,触发滑动手势事件的最小滑动距离为0PanGesture({ fingers: 1, direction: null, distance: 0 })// 滑动手势识别成功回调.onActionStart(() => {this.dragItem = itemthis.dragRefOffset = 0})// 滑动手势移动过程中回调.onActionUpdate((event: GestureEvent) => {this.offsetY = event.offsetY - this.dragRefOffsetthis.neighborItem = -1let index = this.arr.indexOf(item)let curveValue = curves.initCurve(Curve.Sharp)let value: number = 0// 根据位移计算相邻项的缩放if (this.offsetY < 0 && index > 0) {value = curveValue.interpolate(-this.offsetY / this.itemIntv)this.neighborItem = this.arr[index-1]this.neighborScale = 1 - value / 20console.info('neighborScale:' + this.neighborScale.toString())} else if (this.offsetY > 0 && index < this.arr.length - 1) {value = curveValue.interpolate(this.offsetY / this.itemIntv)this.neighborItem = this.arr[index+1]this.neighborScale = 1 - value / 20}// 根据位移交换排序if (this.offsetY > this.itemIntv / 2 && index < this.arr.length - 1) {// 设置显式动画曲线animateTo({ curve: curves.interpolatingSpring(0, 1, 400, 38) }, () => {this.offsetY -= this.itemIntvthis.dragRefOffset += this.itemIntvthis.itemMove(index, index + 1)})} else if (this.offsetY < -this.itemIntv / 2 && index > 0) {animateTo({ curve: curves.interpolatingSpring(0, 1, 400, 38) }, () => {this.offsetY += this.itemIntvthis.dragRefOffset -= this.itemIntvthis.itemMove(index, index - 1)})}})// 滑动手势识别成功,手指抬起后触发回调.onActionEnd((event: GestureEvent) => {console.info(this.arr.toString())animateTo({ curve: curves.interpolatingSpring(0, 1, 400, 38) }, () => {this.dragItem = -1this.neighborItem = -1})animateTo({curve: curves.interpolatingSpring(14, 1, 170, 17), delay: 150}, () => {this.scaleItem = -1})}))// 滑动手势识别成功,接收到触摸取消事件触发回调.onCancel(() => {animateTo({ curve: curves.interpolatingSpring(0, 1, 400, 38) }, () => {this.dragItem = -1this.neighborItem = -1})animateTo({curve: curves.interpolatingSpring(14, 1, 170, 17), delay: 150}, () => {this.scaleItem = -1})}))// 设置页面转场时的纵向的平移距离}, (item: number) => item.toString())}.layoutWeight(1)}.width('100%').height('100%').backgroundColor(0xDCDCDC).padding({ top: 5 })}}
}

http://www.dtcms.com/a/483522.html

相关文章:

  • 【橘子ES】如何本地调试ES源码
  • Leetcodde 3713. Longest Balanced Substring I
  • 福州网站制作费用学seo优化
  • # 超简单四步完成FreeRTOS移植到STM32
  • 专业做电子的外贸网站嘉兴做网站美工的工作
  • 山东青岛网站设计网站制定公司
  • 网站制作理念深圳12个区排名
  • Flutter---底部导航框架
  • 宁波网站开发服务平台的运营推广怎么做
  • 建设局网站漠河网站建设规模设想
  • 购物网站后台好管理吗wordpress网站的优化
  • 【深入浅出PyTorch】--7.1.PyTorch可视化1
  • 中企动力做的网站被镜像wordpress 大气模板
  • 东莞中小型网站建设现在做跨境电商还能赚钱吗
  • wordpress自建站上可以买卖网站备案掉了怎么办
  • 杂谈6.0
  • C语言--预处理
  • 电子商务网站建设核心是河南省城乡建设厅网站首页
  • 个人网站备案名称咋制作网站
  • 做网站需要考虑什么金融网站开发文档
  • 白细胞偏高:揪出原因,科学应对
  • 【开题答辩过程】以《助农电商信息管理系统的设计与实现》为例,不会开题答辩的可以进来看看
  • HT4822立体声耳机放大器:打造高品质音频
  • 使用NVIDIA TAO 6和DeepStream 8构建实时视觉检测管道
  • Java并发机制的底层实现原理:从CPU到JVM的全面解析
  • 判断web代理服务未生效以及测试服务是否生效
  • 视觉检测设备-AI视觉质量检测方案提升效率
  • 原生多模态AI架构:统一训练与跨模态推理的系统实现与性能优化
  • 荣耀手机商城官方网站入口网站制作公司深圳
  • 网站内容运营免费建网站的服务器