文档开发者中心
我的
|

HarmonyOS 5

编辑

Grid组件编辑模式打开后,仍然不可以拖动组件该如何解决
点赞
收藏
回复
5
分享
举报
浏览102 发布于2025-12-18 15:54河南
全部评论
最多点赞
最新发布
最早发布

Grid拖拽:

  1. 通过属性editMode设置Grid是否进入编辑模式,进入编辑模式可以拖拽Grid组件内部GridItem。
  2. 在onItemDragStart回调中设置拖拽过程中显示的图片。
  3. 在onItemDrop中获取拖拽起始位置,和拖拽插入位置,并在onItemDrop中完成交换数组位置逻辑。
  4. 设置属性supportAnimation(true)支持动画。

说明

预览器窗口不支持显示拖拽跟手。

收起
自动换行
深色代码主题
复制
import { GridDataSource } from './GridDataSource';
@Entry
@Component
struct GridExample {
  numbers: GridDataSource = new GridDataSource([]);
  scroller: Scroller = new Scroller();
  @State text: string = 'drag';
  @Builder pixelMapBuilder() { //拖拽过程样式
    Column() {
      Text(this.text)
        .fontSize(16)
        .backgroundColor(0xF9CF93)
        .width(80)
        .height(80)
        .textAlign(TextAlign.Center)
    }
  }
  aboutToAppear() {
    let list: string[] = [];
    for (let i = 1; i <= 15; i++) {
      list.push(i + '');
    }
    this.numbers = new GridDataSource(list);
  }
  changeIndex(index1: number, index2: number) { //交换数组位置
    this.numbers.swapItem(index1, index2);
  }
  build() {
    Column({ space: 5 }) {
      Grid(this.scroller) {
        LazyForEach(this.numbers, (day: string) => {
          GridItem() {
            Text(day)
              .fontSize(16)
              .backgroundColor(0xF9CF93)
              .width(80)
              .height(80)
              .textAlign(TextAlign.Center)
          }
        }, (day: string) => day)
      }
      .columnsTemplate('1fr 1fr 1fr')
      .columnsGap(10)
      .rowsGap(10)
      .width('90%')
      .backgroundColor(0xFAEEE0)
      .height(300)
      .editMode(true) //设置Grid是否进入编辑模式,进入编辑模式可以拖拽Grid组件内部GridItem
      .supportAnimation(true) // 设置支持动画
      .onItemDragStart((event: ItemDragInfo, itemIndex: number) => { //第一次拖拽此事件绑定的组件时,触发回调。
        this.text = this.numbers.getData(itemIndex);
        return this.pixelMapBuilder(); //设置拖拽过程中显示的图片。
      })
      .onItemDrop((event: ItemDragInfo, itemIndex: number, insertIndex: number, isSuccess: boolean) => { //绑定此事件的组件可作为拖拽释放目标,当在本组件范围内停止拖拽行为时,触发回调。
        // isSuccess=false时,说明drop的位置在grid外部;insertIndex > length时,说明有新增元素的事件发生
        if (!isSuccess || insertIndex >= this.numbers.totalCount()) {
          return;
        }
        console.info('itemIndex:' + itemIndex + ', insertIndex:' + insertIndex); //itemIndex拖拽起始位置,insertIndex拖拽插入位置
        this.changeIndex(itemIndex, insertIndex);
      })
    }.width('100%').margin({ top: 5 })
  }
}

效果图: 

cke_1299.png

展开全部
3楼回复于2025-12-19 01:27 来自北京

背景知识:

按照 Grid网格元素拖拽交换 流程:
image.png

问题解决:

示例代码:

收起
自动换行
深色代码主题
复制
@Entry
@Component
struct GridPage {
    @State message: string = 'Hello World';
    @State list: Array<string> = []
    @State imageNum: number = 0;

    aboutToAppear(): void {
        for (let i = 0; i < 10; i++) {
            this.list.push("Item" + i)
        }
    }

    @Builder
    pixelMapBuilder() {
        Column() {
            Text(this.list[this.imageNum])
                .fontSize(20)
                .fontColor(Color.Black)
                .fontWeight(FontWeight.Bold)
                .textAlign(TextAlign.Center)
        }
        .width(106)
        .height(73)
        .justifyContent(FlexAlign.Center)
        .backgroundColor("#F1F3F5")
        .zIndex(1)
        .scale({ x: 1.05, y: 1.05 })
        .translate({ x: 0, y: 0 })
        .borderRadius(10)
    }


    // [Start data_exchange_start]
    changeIndex(index1: number, index2: number) {
        let tmp = this.list.splice(index1, 1);
        this.list.splice(index2, 0, tmp[0])
    }
    // [End data_exchange_start]

    build() {
        Column() {
            Grid() {
                ForEach(this.list, (item: string, index: number) => {
                    GridItem() {
                        Column() {
                            Text(item)
                                .fontSize(20)
                                .fontColor(Color.Black)
                                .fontWeight(FontWeight.Bold)
                                .textAlign(TextAlign.Center)
                        }
                        .width("100%")
                        .height(73)
                        .justifyContent(FlexAlign.Center)
                        .borderRadius(10)
                        .backgroundColor("#F1F3F5")
                        .animation({ curve: Curve.Sharp, duration: 300 })

                    }

                }, (item: string, index: number) => item)
            }
            .width("100%")
            //总要,true开启,false不开启
            .editMode(true)
            .scrollBar(BarState.Off)
            .columnsTemplate('1fr 1fr 1fr 1fr')
            .columnsGap(12)
            .rowsGap(12)
            .margin({ top: 5 })
            .onItemDragStart((_, itemIndex: number) => {
                this.list.findIndex((v:String,i:number,obj:string[])=>{
                    if(v == this.list[itemIndex]){
                        this.imageNum = i
                    }
                })
                // this.imageNum = this.list[itemIndex];
                return this.pixelMapBuilder();
            })
            .onItemDrop((_, itemIndex: number, insertIndex: number, isSuccess: boolean) => {
                if (!isSuccess || insertIndex >= this.list.length) {
                    return;
                }
                this.changeIndex(itemIndex, insertIndex);
            })
        }
        .height('100%')
        .width('100%')
    }
}

演示:

cke_11163.gif

展开全部
5楼回复于2025-12-23 10:14 来自广东
希望楼主提供基础布局代码,有可能是存在手势拦截各种原因 需要结合代码进行分析
4楼回复于2025-12-19 13:37 来自湖南
2楼回复于2025-12-19 01:16 来自浙江
  1. 通过属性editMode设置Grid是否进入编辑模式,进入编辑模式可以拖拽Grid组件内部GridItem。
  2. 在onItemDragStart回调中设置拖拽过程中显示的图片。
  3. 在onItemDrop中获取拖拽起始位置,和拖拽插入位置,并在onItemDrop中完成交换数组位置逻辑。

    文档示例:

    import { GridDataSource } from './GridDataSource';

    @Entry

    @Component

    struct GridExample {

      numbers: GridDataSource = new GridDataSource([]);

      scroller: Scroller = new Scroller();

      @State text: string = 'drag';

      @Builder pixelMapBuilder() { //拖拽过程样式

        Column() {

          Text(this.text)

            .fontSize(16)

            .backgroundColor(0xF9CF93)

            .width(80)

            .height(80)

            .textAlign(TextAlign.Center)

        }

      }

      aboutToAppear() {

        let list: string[] = [];

        for (let i = 1; i <= 15; i++) {

          list.push(i + '');

        }

        this.numbers = new GridDataSource(list);

      }

      changeIndex(index1: number, index2: number) { //交换数组位置

        this.numbers.swapItem(index1, index2);

      }

      build() {

        Column({ space: 5 }) {

          Grid(this.scroller) {

            LazyForEach(this.numbers, (day: string) => {

              GridItem() {

                Text(day)

                  .fontSize(16)

                  .backgroundColor(0xF9CF93)

                  .width(80)

                  .height(80)

                  .textAlign(TextAlign.Center)

              }

            }, (day: string) => day)

          }

          .columnsTemplate('1fr 1fr 1fr')

          .columnsGap(10)

          .rowsGap(10)

          .width('90%')

          .backgroundColor(0xFAEEE0)

          .height(300)

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

          .supportAnimation(true) // 设置支持动画

          .onItemDragStart((event: ItemDragInfo, itemIndex: number) => { //第一次拖拽此事件绑定的组件时,触发回调。

            this.text = this.numbers.getData(itemIndex);

            return this.pixelMapBuilder(); //设置拖拽过程中显示的图片。

          })

          .onItemDrop((event: ItemDragInfo, itemIndex: number, insertIndex: number, isSuccess: boolean) => { //绑定此事件的组件可作为拖拽释放目标,当在本组件范围内停止拖拽行为时,触发回调。

            // isSuccess=false时,说明drop的位置在grid外部;insertIndex > length时,说明有新增元素的事件发生

            if (!isSuccess || insertIndex >= this.numbers.totalCount()) {

              return;

            }

            console.info('itemIndex:' + itemIndex + ', insertIndex:' + insertIndex); //itemIndex拖拽起始位置,insertIndex拖拽插入位置

            this.changeIndex(itemIndex, insertIndex);

          })

        }.width('100%').margin({ top: 5 })

      }

    }

展开全部
1楼回复于2025-12-19 00:23 来自广西
写回答
新增插入模板功能
一键使用模板,快速填写内容,轻松发帖~
知道了
  • 为了保障您的信息安全,请勿上传您的敏感个人信息(如您的密码等信息)和您的敏感资产信息(如关键源代码、签名私钥、调试安装包、业务日志等信息),且您需自行承担由此产生的信息泄露等安全风险。
  • 如您发布的内容为转载内容,请注明内容来源。

我要提问题

了解社区公约,与您携手共创和谐专业的开发者社区。