HarmonyOS鸿蒙Next中拖拽Text进入Grid,触发onDrop,修改数据源直接不显示了?
HarmonyOS鸿蒙Next中拖拽Text进入Grid,触发onDrop,修改数据源直接不显示了?
import { Prompt } from '@kit.ArkUI';
import { unifiedDataChannel } from '@kit.ArkData';
import { hilog } from '@kit.PerformanceAnalysisKit';
@Entry
@Component
struct GridExample {
@State numbers: string[] = [];
// 添加图片资源引用声明
@State dragImage: Resource = $r('app.media.app_icon');
scroller: Scroller = new Scroller();
@State text: string = 'drag';
@State insertIndex: number = -1
@Builder
pixelMapBuilder() {
Column() {
Image($r('app.media.app_icon')) // 使用本地图片资源
.width(80)
.height(80)
.objectFit(ImageFit.Contain) // 保持图片比例
}
}
aboutToAppear() {
for (let i = 1; i <= 15; i++) {
this.numbers.push(i + '');
}
}
addNewItem(text: string, insertIndex: number) {
// 在指定位置插入新项目
this.numbers.splice(insertIndex, 0, text);
}
build() {
Column({ space: 5 }) {
// 外部可拖拽文本
Text('拖拽我')
.fontSize(16)
.backgroundColor(0xD2B48C)
.width(120)
.height(40)
.textAlign(TextAlign.Center)
.onDragStart((event: DragEvent, extraParams?: string) => {
// const data: unifiedDataChannel.PlainText = new unifiedDataChannel.PlainText()
// data.textContent = "111"
// const udata = new unifiedDataChannel.UnifiedData(data)
// event.setData(udata)
const dragItemInfo: DragItemInfo = {
builder: this.pixelMapBuilder(),
extraInfo: '1313131313'
}
return dragItemInfo
//return this.pixelMapBuilder();
})
.onClick(() => {
this.numbers.splice(0, 0, "1111");
})
Grid(this.scroller) {
ForEach(this.numbers, (day: string) => {
GridItem() {
Text(day)
.fontSize(16)
.backgroundColor(0xF9CF93)
.width(80)
.height(80)
.textAlign(TextAlign.Center)
}
})
}
.columnsTemplate('1fr 1fr 1fr')
.columnsGap(10)
.rowsGap(10)
.key("1111111")
.backgroundColor(0xFAEEE0)
.height('100%')
// .supportAnimation(true)
//.editMode(true) // 设置Grid是否进入编辑模式,进入编辑模式可以拖拽Grid组件内部GridItem
// .onItemDragStart((event: ItemDragInfo, itemIndex: number) => { // 第一次拖拽此事件绑定的组件时,触发回调。
//
// return this.pixelMapBuilder(); //设置拖拽过程中显示的图片。
//
// })
//
// // 绑定此事件的组件可作为拖拽释放目标,当在本组件范围内停止拖拽行为时,触发回调。
//
// .onItemDrop((event: ItemDragInfo, itemIndex: number, insertIndex: number, isSuccess: boolean) => {
// // 获取拖拽的文本数据
// //const draggedText = event.extraInfo;
// // if (draggedText) {
// // this.addNewItem(draggedText, insertIndex);
// // }
// })
.onDrop((dragEvent: DragEvent) => {
this.numbers.push("10")
const globalX = dragEvent.getWindowX(); // 获取全局X坐标
const globalY = dragEvent.getWindowY(); // 获取全局Y坐标
// 将全局坐标转换为相对于Grid的坐标
const gridX = globalX - this.scroller.currentOffset().xOffset;
const gridY = globalY - this.scroller.currentOffset().yOffset;
hilog.info(1, '[DEMO]', gridX + "")
hilog.info(1, '[DEMO]', gridY + "")
// 计算当前拖拽位置的索引
const colCount = 3; // 根据columnsTemplate设置
const itemWidth = 80 + 50; // 项目宽度+列间距
const itemHeight = 80 + 10; // 项目高度+行间距
const colIndex = Math.floor(gridX / itemWidth);
const rowIndex = Math.floor(gridY / itemHeight);
const insertIndex = (rowIndex * colCount + colIndex) - 3;
this.numbers = this.numbers.splice(insertIndex, 0, "1111");
// hilog.info(1, '[DEMO]', insertIndex + "")
//
// //this.numbers = this.numbers.splice(insertIndex, 0, "1111");
// this.numbers.push("10")
// hilog.info(1, '[DEMO]', JSON.stringify(this.numbers))
// this.addNewItem("1111", insertIndex)
// hilog.info(1, '[DEMO]',JSON.stringify(this.numbers.splice(insertIndex, 0, "1111")))
})
}.width('100%').margin({ top: 5 })
}
}
谁知道为啥?
更多关于HarmonyOS鸿蒙Next中拖拽Text进入Grid,触发onDrop,修改数据源直接不显示了?的实战教程也可以访问 https://www.itying.com/category-93-b0.html
4 回复
在onDrop事件中直接使用splice方法修改数组会破坏响应式更新机制
尝试如下修改
.onDrop((dragEvent: DragEvent) => {
const data = dragEvent.getData()?.getFirstPlainText(); // 获取拖拽数据
if (!data) return;
// 计算有效插入位置
const offset = this.scroller.currentOffset();
const gridX = dragEvent.getWindowX() - Math.abs(offset.xOffset);
const gridY = dragEvent.getWindowY() - Math.abs(offset.yOffset);
const colCount = 3;
const itemWidth = 80 + 10; // 包含列间距
const itemHeight = 80 + 10; // 包含行间距
const colIndex = Math.floor(gridX / itemWidth);
const rowIndex = Math.floor(gridY / itemHeight);
let insertIndex = rowIndex * colCount + colIndex;
// 边界保护
insertIndex = Math.max(0, Math.min(insertIndex, this.numbers.length));
// 更新数据源
this.numbers.splice(insertIndex, 0, data);
this.numbers = [...this.numbers]; // 触发响应式更新
})
更多关于HarmonyOS鸿蒙Next中拖拽Text进入Grid,触发onDrop,修改数据源直接不显示了?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
算不算系统bug,
这个问题是由于在 onDrop 回调中直接修改 @State 数据源 numbers 数组时,使用了错误的数组操作方法导致的。
在你的代码中,这一行有问题:
this.numbers = this.numbers.splice(insertIndex, 0, "1111");
splice() 方法返回的是被删除的元素数组,而不是修改后的新数组。当你将 splice() 的返回值赋给 this.numbers 时,实际上是将一个空数组(因为没有删除任何元素)赋值给了 this.numbers,导致所有内容消失。
正确的做法应该是:
// 方法1:直接修改原数组,然后重新赋值触发刷新
this.numbers.splice(insertIndex, 0, "1111");
this.numbers = [...this.numbers]; // 创建新数组引用触发UI更新
// 方法2:使用数组扩展运算符
this.numbers = [
...this.numbers.slice(0, insertIndex),
"1111",
...this.numbers.slice(insertIndex)
];
另外,你的坐标计算逻辑可能也有问题:
itemWidth和itemHeight应该使用 Grid 的实际布局参数- 坐标转换时需要考虑 Grid 的滚动偏移量
建议先修复数组操作问题,如果还有显示问题,再检查坐标计算逻辑。

