1. Harmony开发 List、Grid拖动自定义排序实现
1.1. List拖动功能
本示例基于显式动画、List组件实现了ListItem的上下拖动、ListItem切换以及ListItem插入的效果。
实现思路:List手势拖动
@Entry
@Component
struct ListDragPage {
@State private arr: string[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14].map((value) => value.toString())
private listScroller: ListScroller = new ListScroller();
private dragIndex: number = -1
private originDragIndex: number = -1
@State itemOffsetList: number[] = []
private itemHeight: number = 100
private listMargin: number = 10
private itemTotalHeight: number = 110
// dragItem距离List组件顶部的距离
private dragOffsetY: number = 0
// dragItem相对于List滚动顶部的距离
private relativeOffsetY: number = 0
// List组件能滑动的最大距离
listMaxScrollOffsetY: number = 0
// List组件开始拖动时的偏移
originListOffsetY: number = 0
// list组件规格
private listArea: Area = {
width: 0,
height: 0,
position: {
},
globalPosition: {
}
}
aboutToAppear(): void {
this.itemOffsetList = new Array<number>(this.arr.length)
}
initState() {
for (let i = 0; i < this.itemOffsetList.length; i++) {
this.itemOffsetList[i] = 0
}
this.dragIndex = -1
this.originDragIndex = -1
this.dragOffsetY = 0
this.originListOffsetY = this.listScroller.currentOffset().yOffset
}
startDragItem(dragIndex: number) {
this.initState()
animateTo({
curve: Curve.Linear }, () => {
this.dragIndex = dragIndex
this.originDragIndex = dragIndex
})
}
increaseDragIndex(eventOffsetY: number) {
let tmp = this.arr.splice(this.dragIndex, 1)
this.arr.splice(this.dragIndex + 1, 0, tmp[0])
this.dragIndex = this.dragIndex + 1
this.itemOffsetList[this.dragIndex] =
eventOffsetY - (this.dragIndex - this.originDragIndex) * this.itemTotalHeight +
this.listScroller.currentOffset().yOffset - this.originListOffsetY
this.itemOffsetList[this.dragIndex - 1] = this.itemTotalHeight
animateTo({
curve: Curve.Sharp, duration: 100 }, () => {
this.itemOffsetList[this.dragIndex - 1] = 0
})
}
decreaseDragIndex(eventOffsetY: number) {
let tmp = this.arr.splice(this.dragIndex, 1)
this.arr.splice(this.dragIndex - 1, 0, tmp[0])
this.dragIndex = this.dragIndex - 1
this.itemOffsetList[this.dragIndex] =
eventOffsetY - (this.dragIndex - this.originDragIndex) * this.itemTotalHeight +
this.listScroller.currentOffset().yOffset - this.originListOffsetY
this.itemOffsetList[this.dragIndex + 1] = -this.itemTotalHeight
animateTo({
curve: Curve.Sharp, duration: 100 }, () => {
this.itemOffsetList[this.dragIndex + 1] = 0
})
}
cancelDrag() {
this.initState()
}
endDragItem() {
animateTo({
curve: Curve.Sharp, duration: 100 }, () => {
this.initState()
})
}
build() {
Column() {
List({
space: this.listMargin