Grid实现拖拽交换排序 原创

一路向北545
发布于 2024-12-14 17:12
3443浏览
2收藏

一、介绍

Grid 网格元素拖拽交换功能的实现,依靠的是 Grid 容器组件、组合手势以及显式动画这三者的结合。其中,Grid 容器组件的作用在于构建网格元素布局;组合手势的用途是达成元素拖拽交换的效果;显式动画则是为元素拖拽交换过程增添动画效果。

二、预览效果

Grid实现拖拽交换排序-鸿蒙开发者社区


三、实现步骤

(1)创建数据作为Grid的数据来源


  @State data: string[] = []
  aboutToAppear(): void {
    for (let index = 0; index < 9; index++) {
      this.data.push(`Item${index}`)
    }
  }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.


(2)Grid加载数据源显示UI


Grid() {
        ForEach(this.data, (item: string) => {
          GridItem() {
            Text(item)
              .width(100)
              .height(100)
              .border({ width: 1, color: Color.Grey })
              .borderRadius(8)
              .textAlign(TextAlign.Center)
          }
        })

      }
      .columnsGap(10)
      .rowsGap(10)
      .height(320)
      .columnsTemplate('1fr 1fr 1fr')
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.


(3)第一次拖拽此事件绑定的组件时,触发回调。


 .onItemDragStart((event: ItemDragInfo, itemIndex: number) => {
        return this.pixelMapBuilder(this.data[itemIndex]); //设置拖拽过程中显示的组件
      })
  • 1.
  • 2.
  • 3.


  @Builder
  pixelMapBuilder(item: string) { //拖拽过程样式
    Column() {
      Text(item)
        .width(120)
        .height(120)
        .border({ width: 1, color: Color.Grey })
        .borderRadius(8)
        .textAlign(TextAlign.Center)
        .backgroundColor(Color.Yellow)
    }
  }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.


(4)拖拽结束逻辑处理


 .onItemDrop((event: ItemDragInfo, itemIndex: number, insertIndex: number, isSuccess: boolean) => {
        if (!isSuccess || insertIndex >= this.data.length) {
          return
        }
         //itemIndex拖拽起始位置,insertIndex拖拽插入位置
        this.changeIndex(itemIndex, insertIndex)
      })
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.


isSuccess=false时,说明drop的位置在grid外部;insertIndex > length时,说明有新增元素的事件发生,此种情况不做处理

​​

​(5)交换数组位置以实现排序效果


changeIndex(index1: number, index2: number) { //交换数组位置
    let tmp = this.data.splice(index1, 1);
    this.data.splice(index2, 0, tmp[0])
  }
  • 1.
  • 2.
  • 3.
  • 4.


四、注意事项

(1)设置Grid是否进入编辑模式需要设置 editMode(true) ,进入编辑模式可以拖拽Grid组件内部GridItem

(2)内容排序动画需要设置  supportAnimation(true),否则会没有动画

(3)当拖拽的item在Grid外部时的情况需要排除掉,不然排序会错乱


五、完整代码


@Entry
@Component
struct Index {
  @State data: string[] = []

  aboutToAppear(): void {
    for (let index = 0; index < 9; index++) {
      this.data.push(`Item${index}`)
    }
  }

  changeIndex(index1: number, index2: number) { //交换数组位置
    let tmp = this.data.splice(index1, 1);
    this.data.splice(index2, 0, tmp[0])
  }

  build() {
    Column() {
      Grid() {
        ForEach(this.data, (item: string) => {
          GridItem() {
            Text(item)
              .width(100)
              .height(100)
              .border({ width: 1, color: Color.Grey })
              .borderRadius(8)
              .textAlign(TextAlign.Center)
          }
        })

      }
      .columnsGap(10)
      .rowsGap(10)
      .height(320)
      .columnsTemplate('1fr 1fr 1fr')
      .supportAnimation(true)
      .editMode(true) //设置Grid是否进入编辑模式,进入编辑模式可以拖拽Grid组件内部GridItem
      .onItemDragStart((event: ItemDragInfo, itemIndex: number) => { //第一次拖拽此事件绑定的组件时,触发回调。
        return this.pixelMapBuilder(this.data[itemIndex]); //设置拖拽过程中显示的图片。
      })
      .onItemDrop((event: ItemDragInfo, itemIndex: number, insertIndex: number, isSuccess: boolean) => {
        if (!isSuccess || insertIndex >= this.data.length) {
          return
        }
        this.changeIndex(itemIndex, insertIndex)
      })
    }
    .height('100%')
    .width('100%')
    .padding(10)
    .justifyContent(FlexAlign.Center)
    .alignItems(HorizontalAlign.Center)
  }

  @Builder
  pixelMapBuilder(item: string) { //拖拽过程样式
    Column() {
      Text(item)
        .width(120)
        .height(120)
        .border({ width: 1, color: Color.Grey })
        .borderRadius(8)
        .textAlign(TextAlign.Center)
        .backgroundColor(Color.Yellow)
    }
  }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
1
收藏 2
回复
举报
1
1
2
1条回复
按时间正序
/
按时间倒序
wx62721b23576f8
wx62721b23576f8

有合并单元格后grid排序的例子吗

回复
2024-12-26 10:30:55


回复
    相关推荐