[Daily HarmonyOS Next Knowledge] Watermark Addition, List UI Refresh, Scroll Component Overlay, Worker Network Requests, Click Events
1. Is there a method to add watermarks to UI in HarmonyOS?
Refer to the demo:
@Entry
@Component
struct PageWatermark {
private settings: RenderingContextSettings = new RenderingContextSettings(true)
private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
@Builder Watermark() {
Canvas(this.context)
.width("100%") .height("100%")
.hitTestBehavior(HitTestMode.Transparent)
.onReady(() => {
this.context.fillStyle = '#10000000'
this.context.font = "16vp"
this.context.textAlign = "center"
this.context.textBaseline = "middle"
// Draw text watermarks here; image watermarks are also possible
for (let i = 0; i < this.context.width / 120; i++) {
this.context.translate(120, 0)
let j = 0
for (; j < this.context.height / 120; j++) {
this.context.rotate(-Math.PI / 180 * 30)
// The watermark data here is hardcoded; replace it with your own watermark
this.context.fillText("Watermark Watermark Watermark", -60, -60)
this.context.rotate(Math.PI / 180 * 30)
this.context.translate(0, 120) }
this.context.translate(0, -120 * j)
}
})
}
build() {
Column() {
Text("No data").fontColor("#495057")
Image($r("app.media.startIcon"))
.width(300)
.layoutWeight(1)
.overlay(this.Watermark())
.width("100%")
}
.height('100%')
.width('100%')
}
}
2. In HarmonyOS, when clicking a list item, how to modify the property status of the current item and refresh the UI based on property changes?
Refer to the demo:
export class ListModel {
title: string;
content: string;
isComplete: boolean;
constructor(title: string, content: string, isComplete: boolean) {
this.title = title;
this.content = content;
this.isComplete = isComplete;
}
}
@Entry
@Component
struct SyncPage {
@State ListData: Array<ListModel> = [
new ListModel('Title 1', 'Content 1', true),
new ListModel('Title 2', 'Content 2', false),
new ListModel('Title 3', 'Content 3', false),
];
build() {
Column() {
List() {
ForEach(this.ListData, (item: ListModel, index: number) => {
ListItem() {
Row() {
Row() {
Text(item.title)
Text(item.content).fontColor('#999999').fontSize(13)
}
Image(item.isComplete ? $r('app.media.ic_personal_focus') : $r('app.media.ic_personal_normal'))
.width(20)
.height(20)
.margin(10)
}
.justifyContent(FlexAlign.SpaceBetween)
.width('100%')
.alignItems(VerticalAlign.Center)
.height(80)
.onClick(() => {
let status = !item.isComplete
this.ListData.map((el, itemIndex) => {
if (itemIndex !== index) {
el.isComplete = false
}
})
this.ListData.splice(index, 1, new ListModel(item.title, item.content, status))
})
}
})
}
Button('Confirm', { type: ButtonType.Normal })
.onClick(() => {
console.log('Print selected data in listData')
})
}
}
}
3. When overlaying a component on a Scroll, how to set margins, width, and height?
Refer to the demo:
@Entry
@Component
struct NestedScroll {
@State listPosition: number = 0; // 0 for scrolling to the top of the List, 1 for the middle, 2 for the bottom.
private arr: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
private scrollerForScroll: Scroller = new Scroller()
private scrollerForList: Scroller = new Scroller()
build() {
Flex() {
Scroll(this.scrollerForScroll) {
Column() {
List({ space: 20, scroller: this.scrollerForList }) {
ForEach(this.arr, (item: number) => {
ListItem() {
Text("ListItem" + item)
.width("100%")
.height("100%")
.borderRadius(15)
.fontSize(16)
.textAlign(TextAlign.Center)
.backgroundColor(Color.White)
}.width("100%").height(100)
}, (item: string) => item)
}
.width("100%")
.height("50%")
.edgeEffect(EdgeEffect.None)
.friction(0.6)
.onReachStart(() => {
this.listPosition = 0
})
.onReachEnd(() => {
this.listPosition = 2
})
.onScrollFrameBegin((offset: number) => {
if ((this.listPosition == 0 && offset <= 0) || (this.listPosition == 2 && offset >= 0)) {
this.scrollerForScroll.scrollBy(0, offset)
return { offsetRemain: 0 }
}
this.listPosition = 1
return { offsetRemain: offset };
})
AreaTest()
}
}
.width("100%").height("100%")
}.width('100%').height('100%').backgroundColor(0xDCDCDC).padding(20)
}
}
@Component struct AreaTest {
build() {
Text("Scroll Area")
.width("100%")
.height("40%")
.backgroundColor(0X330000FF)
.fontSize(16)
.textAlign(TextAlign.Center)
.margin(90)
}
}
4. In HarmonyOS, how to process all network requests through multi-threading using workers?
For frequent network requests and database storage—operations that are time-consuming and have logical sequences—use workers. Reference: https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/worker-introduction-V5
Main role of Worker: Provides a multi-threading runtime environment for applications, allowing scripts to run in background threads separately from the host thread. This avoids blocking the host thread with compute-intensive or high-latency tasks. For specific interface information and usage, see Worker.
Worker operation mechanism diagram
- The thread creating the Worker is the host thread (not necessarily the main thread; worker threads can also create Worker child threads). The Worker's own thread is the Worker child thread (or Actor thread/worker thread).
- Each Worker child thread and host thread have independent instances (infrastructure, objects, code segments, etc.), so starting each Worker incurs memory overhead. Limit the number of Worker child threads.
- Communication between Worker child threads and the host thread is message-based, using serialization for command and data interaction.
Precautions:
- When creating a Worker, there are manual and automatic methods. Manual creation requires configuring the Worker thread directory and files.
- The path rules for Worker thread files in the constructor vary by version.
- Manually manage the Worker lifecycle. A maximum of 64 Worker child threads can run simultaneously.
- Worker threads can only use thread-safe libraries (e.g., non-thread-safe UI libraries are unsupported).
- Serialized data is limited to 16MB.
- Register the
onerror
interface in the host thread to avoid jscrash on Worker thread exceptions. - Cross-HAP Worker thread file usage is unsupported.
- Configure dependencies for HAR/HSP before referencing them.
-
AppStorage
is unsupported in Worker threads.
5. In HarmonyOS, how to better capture single-click events?
Using TapGesture({count: 1}).onAction((event: GestureEvent) => { Code segment A })
may trigger Code segment A even if the finger is lifted after a delay or after sliding. For typical single-clicks requiring quick lifts, use a GestureGroup
with exclusive recognition mode, adding empty long-press and pan gestures.
Sample code:
Button('Gesture Verification')
.gesture(GestureGroup(GestureMode.Exclusive,
TapGesture({count: 1}).onAction(() => {
// Code segment A
}),
LongPressGesture(),
PanGesture()
))
Top comments (0)