鸿蒙开发:案例集合List:ListItem拖拽(交换位置,过渡动画)

🎯 案例集合List:ListItem拖拽(交换位置,过渡动画)

🌍 案例集合List

🚪 最近开启了学员班级点我欢迎加入(学习相关知识可获得定制礼盒)

🏷️ 效果图

🏷 onMove(拖拽排序)

🏷 onItemDragStart, onItemDragMove, onItemDrop

📖 参考

🧩 拆解

  • 原生(onMove)拖拽
javascript 复制代码
/**
 * 模拟数据
 */
const listData: string[] = ['购物', '体育', '服装', '军事', '电商', '娱乐', '科技']

@Component
export struct listDragAndDrop {
  build() {
    Column({ space: 10 }) {
      Text('可以左右拖拽滑动')
        .fontColor(20)
      List({ space: 10 }) {
        ForEach(listData, (item: string) => {
          ListItem() {
            Text(item)
              .width(80)
              .aspectRatio(1)
              .fontSize(20)
              .fontColor(Color.White)
              .textAlign(TextAlign.Center)
              .backgroundColor('#803c6ad0')
          }
        }, (item: string) => item)
          .onMove((from: number, to: number) => {
            const exchange = listData.splice(from, 1)
            listData.splice(to, 0, exchange[0])
          })
      }
      .height(80)
      .padding({ left: 15, right: 15 })
      .listDirection(Axis.Horizontal)
      .scrollBar(BarState.Off)
      .edgeEffect(EdgeEffect.None)
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
    .alignItems(HorizontalAlign.Center)
  }
}
  • 原生(onItemDragStart, onItemDragMove, onItemDrop)拖拽
javascript 复制代码
@Component
export struct listDragAndDrop {
  /**
   * 模拟数据
   */
  @State listData: string[] = ['购物', '体育', '服装', '军事', '电商', '娱乐', '科技']
  /**
   * 列表构造器
   */
  private listScroller: Scroller = new Scroller()
  /**
   * scale
   */
  @State itemScale: number = 0.75
  /**
   * 当前拖拽某个item的下标
   */
  @State curListItemDragIdx: number = -1
  /**
   * 可视区域的开头组件下标
   */
  @State scrollerStart: number = 0
  /**
   * 可视区域的结尾组件下标
   */
  @State scrollerEnd: number = 0

  /**
   * 拖拽样式
   */
  @Builder
  draggingBuilder(curListItemDragIdx: number) {
    Text(this.listData[curListItemDragIdx])
      .width(80)
      .aspectRatio(1)
      .fontSize(20)
      .fontColor(Color.White)
      .textAlign(TextAlign.Center)
      .backgroundColor('#803c6ad0')
  }

  /**
   * 拖拽结束
   */
  private dragAndDropEnds(idx_1: number, idx_2: number) {
    this.curListItemDragIdx = -1
    this.swapPositions(idx_1, idx_2)
  }

  /**
   * 交换位置
   * @param idx_1
   * @param idx_2
   */
  private swapPositions(idx_1: number, idx_2: number) {
    // 利用中间常量存交换值
    const swapItem = this.listData[idx_1]
    this.listData[idx_1] = this.listData[idx_2]
    this.listData[idx_2] = swapItem
  }

  build() {
    Column({ space: 10 }) {
      Text('可以左右拖拽滑动')
        .fontColor(20)
      List({ space: 10, scroller: this.listScroller }) {
        ForEach(this.listData, (item: string, idx: number) => {
          ListItem() {
            Text(item)
              .width(80)
              .aspectRatio(1)
              .fontSize(20)
              .fontColor(Color.White)
              .textAlign(TextAlign.Center)
              .backgroundColor('#803c6ad0')
              .scale({
                x: this.curListItemDragIdx === idx ? this.itemScale : 1,
                y: this.curListItemDragIdx === idx ? this.itemScale : 1
              })
              .animation({ curve: Curve.Smooth, duration: 200 })
          }
        })
      }
      .height(80)
      .padding({ left: 15, right: 15 })
      .listDirection(Axis.Horizontal)
      .scrollBar(BarState.Off)
      .edgeEffect(EdgeEffect.None)
      .onScrollIndex((start: number, end: number, center: number) => {
        this.scrollerStart = start
        this.scrollerEnd = end
        console.info('scrollerStart', start.toString() + '' + end.toString())

      })
      // 开始拖拽列表元素时触发
      .onItemDragStart((event: ItemDragInfo, curListItemDragIdx: number) => {
        // 拖拽中显示的内容
        return this.draggingBuilder(curListItemDragIdx)
      })
      .onItemDragMove((event: ItemDragInfo, itemIndex: number, insertIndex: number) => {
        // 更新当前拖拽到某个item的下标
        this.curListItemDragIdx = insertIndex

        // 向右滑动
        if (insertIndex === this.scrollerEnd && this.scrollerEnd <= this.listData.length - 1) {
          this.listScroller.scrollToIndex(insertIndex - 2, true)
        }

        // 向左滑动
        if (insertIndex === this.scrollerStart && this.scrollerStart !== 0) {
          this.listScroller.scrollToIndex(insertIndex - 1, true)
        }
      })
      // 拖拽结束
      .onItemDrop((event: ItemDragInfo, itemIndex: number, insertIndex: number, isSuccess: boolean) => {
        // 当前手势没释放 | 插入位置小于0 | 插入位置大于列表长度
        if (!isSuccess || insertIndex < 0 || insertIndex >= this.listData.length) {
          return
        }
        this.dragAndDropEnds(itemIndex, insertIndex)
      })
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
    .alignItems(HorizontalAlign.Center)
  }
}

🌸🌼🌺

相关推荐
贾伟康6 小时前
HarmonyOS API 26 嵌套 Navigation:getParent、父子栈边界与返回分发
harmonyos·arkts·navigation·嵌套路由·navpathstack
行者-全栈开发6 小时前
【鸿蒙心迹】多线程并发实战——TaskPool 与 Worker 选型与踩坑(HarmonyOS 7.x)
华为·harmonyos·多线程并发·worker·taskpool·线程通信·harmonyos 并发
OH_TPC9 小时前
@ohos/aki 源码解读(一):一行绑定背后,宏、模板与索引分发
harmonyos
贾伟康9 小时前
【解压时刻|13】HarmonyOS ArkTS 启动链路审计:从 EntryAbility、AppStore 到 Navigation 首屏
harmonyos·arkts·appstorage·应用启动·entryability
贾伟康10 小时前
【古诗词闯关|12】HarmonyOS ArkTS 单页组件拆分实战:降低题库、闯关与结果弹层耦合
harmonyos·arkts·状态管理·arkui·组件化
威哥爱编程12 小时前
模拟面试智能体开发实战 07:答完一题就点评一题,结构化输出给分建议,让每道题都变成复盘
python·agent·harmonyos
威哥爱编程12 小时前
模拟面试智能体开发实战 08:总评报告先过三道闸,防泄题防夸大防错建议,才敢发到候选人手上
python·agent·harmonyos
熊猫钓鱼>_>1 天前
普通用户视角的端侧智能体验手记【鸿蒙心迹】
开发语言·人工智能·华为·智能手机·性能优化·ai编程·harmonyos
KevinChaos1 天前
阳台小花园开发手记 05|HarmonyOS 7.0 互动卡片:动效进出衔接
华为·harmonyos
WHMONY1 天前
大一独立开发鸿蒙原生 AI Agent:聊聊我为什么死磕端侧模型与“技术平权”
harmonyos