案例背景:
例如当我们在朋友圈分享图片时,选了 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;}
复制代码
评论