🎯 案例集合List:ListItem拖拽(交换位置,过渡动画)
🌍 案例集合List
🚪 最近开启了学员班级点我欢迎加入(学习相关知识可获得定制礼盒)
🏷️ 效果图
🏷 onMove(拖拽排序)

🏷 onItemDragStart, onItemDragMove, onItemDrop

📖 参考
🧩 拆解
- 原生(onMove)拖拽
javascript
/**
* 模拟数据
*/
const listData: string[] = ['购物', '体育', '服装', '军事', '电商', '娱乐', '科技']
@Component
export struct listDragAndDrop {
build() {
Column({ space: 10 }) {
Text('可以左右拖拽滑动')
.fontColor(20)
List({ space: 10 }) {
ForEach(listData, (item: string) => {
ListItem() {
Text(item)
.width(80)
.aspectRatio(1)
.fontSize(20)
.fontColor(Color.White)
.textAlign(TextAlign.Center)
.backgroundColor('#803c6ad0')
}
}, (item: string) => item)
.onMove((from: number, to: number) => {
const exchange = listData.splice(from, 1)
listData.splice(to, 0, exchange[0])
})
}
.height(80)
.padding({ left: 15, right: 15 })
.listDirection(Axis.Horizontal)
.scrollBar(BarState.Off)
.edgeEffect(EdgeEffect.None)
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
.alignItems(HorizontalAlign.Center)
}
}
- 原生(onItemDragStart, onItemDragMove, onItemDrop)拖拽
javascript
@Component
export struct listDragAndDrop {
/**
* 模拟数据
*/
@State listData: string[] = ['购物', '体育', '服装', '军事', '电商', '娱乐', '科技']
/**
* 列表构造器
*/
private listScroller: Scroller = new Scroller()
/**
* scale
*/
@State itemScale: number = 0.75
/**
* 当前拖拽某个item的下标
*/
@State curListItemDragIdx: number = -1
/**
* 可视区域的开头组件下标
*/
@State scrollerStart: number = 0
/**
* 可视区域的结尾组件下标
*/
@State scrollerEnd: number = 0
/**
* 拖拽样式
*/
@Builder
draggingBuilder(curListItemDragIdx: number) {
Text(this.listData[curListItemDragIdx])
.width(80)
.aspectRatio(1)
.fontSize(20)
.fontColor(Color.White)
.textAlign(TextAlign.Center)
.backgroundColor('#803c6ad0')
}
/**
* 拖拽结束
*/
private dragAndDropEnds(idx_1: number, idx_2: number) {
this.curListItemDragIdx = -1
this.swapPositions(idx_1, idx_2)
}
/**
* 交换位置
* @param idx_1
* @param idx_2
*/
private swapPositions(idx_1: number, idx_2: number) {
// 利用中间常量存交换值
const swapItem = this.listData[idx_1]
this.listData[idx_1] = this.listData[idx_2]
this.listData[idx_2] = swapItem
}
build() {
Column({ space: 10 }) {
Text('可以左右拖拽滑动')
.fontColor(20)
List({ space: 10, scroller: this.listScroller }) {
ForEach(this.listData, (item: string, idx: number) => {
ListItem() {
Text(item)
.width(80)
.aspectRatio(1)
.fontSize(20)
.fontColor(Color.White)
.textAlign(TextAlign.Center)
.backgroundColor('#803c6ad0')
.scale({
x: this.curListItemDragIdx === idx ? this.itemScale : 1,
y: this.curListItemDragIdx === idx ? this.itemScale : 1
})
.animation({ curve: Curve.Smooth, duration: 200 })
}
})
}
.height(80)
.padding({ left: 15, right: 15 })
.listDirection(Axis.Horizontal)
.scrollBar(BarState.Off)
.edgeEffect(EdgeEffect.None)
.onScrollIndex((start: number, end: number, center: number) => {
this.scrollerStart = start
this.scrollerEnd = end
console.info('scrollerStart', start.toString() + '' + end.toString())
})
// 开始拖拽列表元素时触发
.onItemDragStart((event: ItemDragInfo, curListItemDragIdx: number) => {
// 拖拽中显示的内容
return this.draggingBuilder(curListItemDragIdx)
})
.onItemDragMove((event: ItemDragInfo, itemIndex: number, insertIndex: number) => {
// 更新当前拖拽到某个item的下标
this.curListItemDragIdx = insertIndex
// 向右滑动
if (insertIndex === this.scrollerEnd && this.scrollerEnd <= this.listData.length - 1) {
this.listScroller.scrollToIndex(insertIndex - 2, true)
}
// 向左滑动
if (insertIndex === this.scrollerStart && this.scrollerStart !== 0) {
this.listScroller.scrollToIndex(insertIndex - 1, true)
}
})
// 拖拽结束
.onItemDrop((event: ItemDragInfo, itemIndex: number, insertIndex: number, isSuccess: boolean) => {
// 当前手势没释放 | 插入位置小于0 | 插入位置大于列表长度
if (!isSuccess || insertIndex < 0 || insertIndex >= this.listData.length) {
return
}
this.dragAndDropEnds(itemIndex, insertIndex)
})
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
.alignItems(HorizontalAlign.Center)
}
}
🌸🌼🌺