Grid实现拖拽交换排序 原创

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

一、介绍

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

二、预览效果

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


三、实现步骤

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


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


(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')


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


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


  @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)
    }
  }


(4)拖拽结束逻辑处理


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


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)设置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)
    }
  }
}

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
收藏
回复
举报
回复
    相关推荐