案例背景:
例如当我们在朋友圈分享图片时,选了 9 张图片,想调整顺序,这时就会用到拖动排序。
最终效果:
实现过程:
1.通过 Picker 组件选取照片展示到 Grid 网格布局中
2.设置编辑模式开启 editMode(true),如果想增加动画效果,可以增加设置 supportAnimation(true)
3.增加开始拖动和拖动结束的回调,开始时设置拖动过程中的组件样式,结束拖拽回调是做顺序调整
展示:
发现好像没有效果呢?
因为开启了 Gride 编辑模式,Image 本身是有拖拽功能的,和 Grid 的 GridItem 拖拽冲突,因此,要禁用掉 Image 的拖拽 draggable(false)
再演示:
禁用掉 Image 的拖拽是可以改变顺序了,但是为什么没有动画效果呢?官方文档查了半天,感觉也没啥问题呀,开始拖拽和结束拖拽的回调都能收到,为啥就没有拖拽的动画效果呢???
最终找到原因是我的 Grid 布局设置是自适应排列
.maxCount(9)
.layoutDirection(GridDirection.Row),没有限制子组件比例,这种布局元素本身就是可根据布局大小动态移动的。
然后将列设置成 3 等分展示 columnsTemplate(‘1fr 1fr 1fr’)
展示:
看着好像是可以排序也有拖拽效果了,但是释放之后,其他元素的位置没有保持当前的位置,而是恢复到了移动前,只是改变了拖拽元素的位置。
下面源码中给出了两种排序模式:
//网格布局
Grid() {
ForEach(this.imgs, (item: string) => {
GridItem() {
Image(item).objectFit(ImageFit.Cover).width(100).height(100)
.draggable(false)
}
}, (item: string) => item)
}
.width('100%')
.height(Math.ceil(this.imgs.length/3)*110)
.columnsTemplate('1fr 1fr 1fr')
// .maxCount(9)
// .layoutDirection(GridDirection.Row)
.columnsGap(10)
.rowsGap(10)
.padding({ left: 20, right: 20 })
.editMode(true)
.supportAnimation(true)
//第一次拖拽此事件绑定的组件时,触发回调。
.onItemDragStart((event: ItemDragInfo, itemIndex: number) => {
//设置拖拽过程中显示的图片。
return this.pixelMapBuilder(this.imgs[itemIndex]);
})
//当在本组件范围内停止拖拽行为时,触发回调。
.onItemDrop((_, itemIndex: number, insertIndex: number,
isSuccess: boolean) => {
if (!isSuccess || insertIndex >= this.imgs.length) {
return;
}
this.changeIndex(itemIndex, insertIndex);
})
//拖拽过程样式
@Builder pixelMapBuilder(imgSource:string) {
Image(imgSource).objectFit(ImageFit.Cover).width(100).height(100)
.draggable(false)
}
//拖拽之后改变元素位置
changeIndex(index1: number, index2: number) {
//这种方式可以保存移动过程中的其他元素位置变化
let tmp = this.imgs.splice(index1, 1);
this.imgs.splice(index2, 0, tmp[0]);
//这种方式只能改变拖动元素和释放位置元素的顺序,其他元素还会恢复之前的顺序
// let temp: string;
// temp = this.imgs[index1];
// this.imgs[index1] = this.imgs[index2];
// this.imgs[index2] = temp;
}
复制代码
评论