[Daily HarmonyOS Next Knowledge] Preventing Repeated Clicks, Dialog Dismissal Interception, Custom Keyboard Focus, Page Hierarchy, Custom Dialog Creation
1. For HarmonyOS onClick events, how to prevent repeated clicks on the same button or toggle if the interval between two clicks is too short?
How to implement a mechanism where repeated clicks on the same button or toggle within a short interval are invalid to prevent repeated clicks?
Reference demo:
// Define a throttle function
function throttle(func: Function, interval: number) {
let lastTime = 0;
return () => {
const nowTime = Date.now();
const remainTime = interval - (nowTime - lastTime);
if (remainTime <= 0) {
lastTime = nowTime;
func();
}
};
}
// Example
Button("Prevent Repeated Clicks").onClick(throttle(() => {
}, 5000))
2. For HarmonyOS CustomDialog, where can I intercept the event that causes the dialog to disappear when the user swipes back?
Explanation:
- When the user performs actions to close the dialog (e.g., clicking the overlay, swiping left/right, using the back button, or pressing ESC), if this callback is registered, the dialog will not close immediately. The callback provides the reason for the dismissal attempt, allowing you to decide whether to allow the dialog to close. Currently, the
reason
parameter does not support theCLOSE_BUTTON
enum value. - You cannot use
onWillDismiss
to intercept dismissals within theonWillDismiss
callback itself.
3. How to control focus acquisition and loss for a custom keyboard in HarmonyOS?
Reference demo:
@Entry
@Component
struct TextInputExample {
controller: TextInputController = new TextInputController()
@State inputValue: string = ""
// Custom keyboard component
@Builder CustomKeyboardBuilder() {
Column() {
Grid() {
ForEach([1, 2, 3, 4, 5, 6, 7, 8, 9, '*', 0, '#'], (item: number | string) => {
GridItem() {
Button(item + "")
.width(110).onClick(() => {
this.inputValue += item
})
}
})
}.maxCount(3).columnsGap(10).rowsGap(10).padding(5)
}.backgroundColor(Color.Gray)
}
build() {
Column() {
Button('Show Keyboard').onClick(() => {
focusControl.requestFocus('txt1')
})
.id('btn1')
Button('Hide Keyboard').onClick(() => {
focusControl.requestFocus('btn1')
})
TextInput({ controller: this.controller, text: this.inputValue }) // Bind custom keyboard
.customKeyboard(this.CustomKeyboardBuilder())
.margin(10)
.border({ width: 1 })
.height('48vp')
.id('txt1')
TextInput({ placeholder: 'No custom keyboard' })
}
}
}
4. In HarmonyOS, does the default router of a HAR module reside in the main window or follow the HSP router layer where it is located?
Scenario:
- Main window A contains an HSP biopsy module (Privacy intermediate page -> Face HAR biopsy page).
- Subwindow B navigates to the HSP privacy intermediate page using
getUIContext().getRouter
. - From the privacy page, navigating to the face HAR page.
Question:
Does the face HAR page need to use getRouter
for navigation? Does its default router belong to the main window or the HSP router layer?
Answer:
According to the UIContext documentation, WindowStage/Window
uses loadContent
to create UI instances, which are bound to specific windows. To access a UI instance via UIContext, a valid window must be traceable from the current context. If the UI context is ambiguous, the call will fail.
-
HSP Page Routing:
https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/in-app-hsp-V5
HSP (Harmony Shared Package) is a dynamic shared package containing code, C++ libraries, resources, and configurations. It shares the host app’s process, package name, and lifecycle.
-
HAR Page Routing (Named Routes):
https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/arkts-routing-V5
Router module enables page navigation and data transfer via URLs.
5. Issues with creating a HarmonyOS CustomDialogController?
showCaptch() {
let alertDialog: CustomDialogController = new CustomDialogController({
builder: DialogSliderCaptch()
})
alertDialog.open()
}
// Works when placed in a page, but fails when made a standalone function (easily reproducible)
function showCaptch() {
let alertDialog: CustomDialogController = new CustomDialogController({
builder: DialogSliderCaptch()
})
alertDialog.open()
}
Explanation:
CustomDialogController
is a page-level component whose lifecycle is tied to the page. When exposed as a standalone function, it loses its page context, leading to failures. Specifically:
- Its lifecycle (initialization, destruction) is managed by the page.
- Detaching it from the page context breaks lifecycle dependencies (e.g.,
build
method). - Thus, exposing it as a function causes unexpected behavior due to lost page bindings.