[Daily HarmonyOS Next Knowledge] Drag to Adjust List Order, Tab Rebound, Custom Pop-up This, State Variable Modifier Enumeration
1. HarmonyOS function implementation (drag to adjust list order)?
Refer to:
import curves from '@ohos.curves';
import Curves from '@ohos.curves'
@Entry
@Component
struct ListItemExample {
@State private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
@State dragItem: number = -1
@State scaleItem: number = -1
@State neighborItem: number = -1
@State neighborScale: number = -1
private dragRefOffset: number = 0
@State offsetX: number = 0
@State offsetY: number = 0
private ITEM_INTV: number = 120
scaleSelect(item: number): number {
if (this.scaleItem == item) {
return 1.05
} else if (this.neighborItem == item) {
return this.neighborScale
} else {
return 1
}
}
itemMove(index: number, newIndex: number): void {
let tmp = this.arr.splice(index, 1)
this.arr.splice(newIndex, 0, tmp[0])
}
build() {
Stack() {
List({ space: 20, initialIndex: 0 }) {
ForEach(this.arr, (item: number) => {
ListItem() {
Text('' + item)
.width('100%')
.height(100)
.fontSize(16)
.textAlign(TextAlign.Center)
.borderRadius(10)
.backgroundColor(0xFFFFFF)
.shadow(this.scaleItem == item ? { radius: 70, color: '#15000000', offsetX: 0, offsetY: 0 } :
{ radius: 0, color: '#15000000', offsetX: 0, offsetY: 0 })
.animation({ curve: Curve.Sharp, duration: 300 })
}
.margin({ left: 12, right: 12 })
.scale({ x: this.scaleSelect(item), y: this.scaleSelect(item) })
.zIndex(this.dragItem == item ? 1 : 0)
.translate(this.dragItem == item ? { y: this.offsetY } : { y: 0 })
.gesture(
// The following combined gestures are recognized in sequence; drag gestures will not be triggered if long-press gestures do not fire normally
GestureGroup(GestureMode.Sequence,
LongPressGesture({ repeat: true })
.onAction((event?: GestureEvent) => {
animateTo({ curve: Curve.Friction, duration: 300 }, () => {
this.scaleItem = item
})
})
.onActionEnd(() => {
animateTo({ curve: Curve.Friction, duration: 300 }, () => {
this.scaleItem = -1
})
}),
PanGesture({ fingers: 1, direction: null, distance: 0 })
.onActionStart(() => {
this.dragItem = item
this.dragRefOffset = 0
})
.onActionUpdate((event: GestureEvent) => {
this.offsetY = event.offsetY - this.dragRefOffset
// console.log('Y:' + this.offsetY.toString())
this.neighborItem = -1
let index = this.arr.indexOf(item)
let curveValue = Curves.initCurve(Curve.Sharp)
let value: number = 0
// Calculate scaling of adjacent items based on displacement
if (this.offsetY < 0) {
value = curveValue.interpolate(-this.offsetY / this.ITEM_INTV)
this.neighborItem = this.arr[index-1]
this.neighborScale = 1 - value / 20;
console.log('neighborScale:' + this.neighborScale.toString())
} else if (this.offsetY > 0) {
value = curveValue.interpolate(this.offsetY / this.ITEM_INTV)
this.neighborItem = this.arr[index+1]
this.neighborScale = 1 - value / 20;
}
// Swap order based on displacement
if (this.offsetY > this.ITEM_INTV / 2) {
animateTo({ curve: curves.interpolatingSpring(0, 1, 400, 38) }, () => {
this.offsetY -= this.ITEM_INTV
this.dragRefOffset += this.ITEM_INTV
this.itemMove(index, index + 1)
})
} else if (this.offsetY < -this.ITEM_INTV / 2) {
animateTo({ curve: curves.interpolatingSpring(0, 1, 400, 38) }, () => {
this.offsetY += this.ITEM_INTV
this.dragRefOffset -= this.ITEM_INTV
this.itemMove(index, index - 1)
})
}
})
.onActionEnd((event: GestureEvent) => {
animateTo({ curve: curves.interpolatingSpring(0, 1, 400, 38) }, () => {
this.dragItem = -1
this.neighborItem = -1
})
animateTo({
curve: curves.interpolatingSpring(14, 1, 170, 17), delay: 150
}, () => {
this.scaleItem = -1
})
})
)
.onCancel(() => {
animateTo({ curve: curves.interpolatingSpring(0, 1, 400, 38) }, () => {
this.dragItem = -1
this.neighborItem = -1
})
animateTo({
curve: curves.interpolatingSpring(14, 1, 170, 17), delay: 150
}, () => {
this.scaleItem = -1
})
})
)
}, (item: number) => item.toString())
}
}.width('100%').height('100%').backgroundColor(0xDCDCDC).padding({ top: 5 })
}}
2. Can the rebound effect be disabled when the HarmonyOS tab component slides to the last index?
When the tab component slides to the last index, can the rebound effect be disabled?
Restrict edge tab scrolling by adding gestures to TabContent. Reference solution:
- Add
.gesture(PanGesture(new PanGestureOptions({ direction: PanDirection.Right })))
to the leftmost TabContent to restrict built-in right swiping. - Add
.gesture(PanGesture(new PanGestureOptions({ direction: PanDirection.Left })))
to the rightmost TabContent to restrict built-in left swiping.
Reference demo:
@Entry
@Component
struct TabsExample {
private controller: TabsController = new TabsController();
build() {
Column() {
Tabs({ barPosition: BarPosition.Start, controller: this.controller }) {
TabContent() {
Column()
.width('100%')
.height('100%')
.backgroundColor(Color.Green)
}
.tabBar('green')
.gesture(PanGesture(new PanGestureOptions({ direction: PanDirection.Right })))
TabContent() {
Column()
.width('100%')
.height('100%')
.backgroundColor(Color.Blue)
}
.tabBar('blue')
.gesture(PanGesture(new PanGestureOptions({ direction: PanDirection.Left })))
// ...
}
.barMode(BarMode.Scrollable)
.barWidth('100%')
.barHeight(60)
.width('100%')
.height('100%')
.backgroundColor(0xF5F5F5)
}
}
}
3. Can a HarmonyOS custom pop-up not be bound to this?
Try making the pop-up global to avoid using this
.
Custom pop-ups do not need to be bound to this
.
4. Can @State not modify enums in HarmonyOS?
Does @State fail to modify enums? Modifying an enum throws an error:
[nodict][page_router_manager.cpp(LoadPage)-(100000:100000:scope)] Update RootComponent Failed or LoadNamedRouter Failed
In ArkTS, using the declare
keyword to modify classes is not supported. This means creating a class with declare
in a struct page may cause issues, including @State-modified enum errors, for the following reasons:
-
declare
keyword not supported: ArkTS does not allow defining classes withdeclare
, as this keyword is for declaring variables/types, not defining classes. Usingdeclare
to define a class in a struct page causes compilation errors. - @State-modified enum error: The
declare
-modified class violates ArkTS specifications, triggering compilation errors that affect dependent code, including @State-modified enums.
5. How to implement cross-page loading in HarmonyOS?
Implement via a splash page during page transitions, replacing the splash page with the target page using router.replaceUrl
, e.g.:
@Entry
@Component
export struct LoadingPage {
@Prop flag: boolean;
build() {
Row() {
LoadingProgress().color(Color.White).width(50).height(50)
}
.height(this.flag ? '100%' : 0)
.width('100%')
.position({ x: 0, y: 0 })
.backgroundColor('#4D000000')
.justifyContent(FlexAlign.Center)
}
}
Refer to replaceUrl
documentation: https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/js-apis-router-V5