[Daily HarmonyOS Knowledge] Network Request Callback Toast Issue, Popup Problem, Disable Popup Return, Navigation Foldable Screen Missing Back Button, Responsive Layout
1. HarmonyOS HTTP request callback causes showToast error?
When using http.HttpRequest.request
to initiate an HTTP request, executing a custom callback function in the promise's then
callback may result in an error when calling toast: [ArkRuntime Log] Error: Internal error. UI execution context not found.
Steps to reproduce:
- Create a request with
http.createHttp();
- Initiate the request with
request.request;
- Process data in
promise.then
and execute the callback function - Use
promptAction.showToast
in the callback function to display the toast
Solution:
The error Internal error. UI execution context not found.
occurs because the promptAction.showToast
interface detects a missing UI instance in the scenario and throws an exception. Bind the UI instance to call the interface and use proper try-catch for exception handling.
@Entry
@Component
struct Index {
@State message: string = 'Obtain the UI instance from the window instance and use the interface through the UI instance';
aboutToAppear(): void {
setTimeout(() => {
// Exception capture
try {
this.getUIContext().getPromptAction().showToast({ message: 'Popup test', duration: 2000 })
} catch (e) {
console.error("Popup exception, error message:" + JSON.stringify(e))
}
}, 1000)
}
build() {
Column() {
Text(this.message)
.id('HelloWorld')
.fontSize(15)
.fontWeight(FontWeight.Bold)
.textAlign(TextAlign.Center)
.width('100%')
}.width('100%')
}
}
2. How to dynamically display content in a custom component bound to a HarmonyOS Button via bindPopup based on external variables?
Since components within bindPopup
are not @component
subcomponents, declarative variables like @state
and @link
cannot be used for passing and updating. Use AppStorage
to create or update properties (e.g., whether a favorite is public), and synchronize updates in bindPopup
via @StorageLink
.
Demo:
export enum PopoverItemType {
Default,
AddVideo,
ManageVideo,
ModifyName,
ModifyPrivacy,
DeleteFolder
}
export interface PopoverItem {
title: string
type: PopoverItemType
}
@Component
export struct CollectionManageMenu {
@State popoverItemList1: PopoverItem[] = []
@State popoverItemList2: PopoverItem[] = []
@StorageLink('pub') pub: string = '0'
aboutToAppear(): void {
this.popoverItemList1 = [
{
title: 'Add Video',
type: PopoverItemType.AddVideo
},
{
title: 'Batch Manage Videos',
type: PopoverItemType.ManageVideo
},
{
title: 'Modify Name',
type: PopoverItemType.ModifyName
},
{
// TODO: The copy should change dynamically based on the status
title: 'Set as Private',
type: PopoverItemType.ModifyPrivacy
},
{
title: 'Delete Favorite',
type: PopoverItemType.DeleteFolder
}
]
this.popoverItemList2 = [
{
title: 'Add Video',
type: PopoverItemType.AddVideo
},
{
title: 'Batch Manage Videos',
type: PopoverItemType.ManageVideo
},
{
title: 'Modify Name',
type: PopoverItemType.ModifyName
},
{
// TODO: The copy should change dynamically based on the status
title: 'Set as Public',
type: PopoverItemType.ModifyPrivacy
},
{
title: 'Delete Favorite',
type: PopoverItemType.DeleteFolder
}
]
}
build() {
Column() {
List() {
ForEach(this.pub == '0' ? this.popoverItemList1 : this.popoverItemList2, (item: PopoverItem, index) => {
ListItem() {
Text(item.title)
}
.height(52)
.padding({
left: 16,
right: 16,
top: 14,
bottom: 14
})
.onClick(() => {
})
}, (item: PopoverItem) => JSON.stringify(item.title))
}
.width('100%')
.scrollBar(BarState.Off)
}
.width(161)
.alignItems(HorizontalAlign.Center)
.borderRadius(8)
}
}
@Entry
@Component
export struct CollectionDetailPageNavBar {
@State showPopover: boolean = false
@State pub: boolean = true
@Builder
manageMenu() {
CollectionManageMenu()
}
build() {
Column() {
Button('Manage')
.width(62)
.height(32)
.borderRadius(16)
.fontSize(15)
.onClick(() => {
this.showPopover = !this.showPopover
})
.bindPopup(
this.showPopover,
{
builder: () => {
this.manageMenu()
},
radius: 8,
enableArrow: true,
placement: Placement.BottomLeft,
targetSpace: 20,
offset: { x: -6 },
onStateChange: (event) => {
if (!event.isVisible) {
this.showPopover = false
}
}
}
)
Button('Change Private/Public Status')
.width(62)
.height(32)
.borderRadius(16)
.fontSize(15)
.onClick(() => {
this.pub = !this.pub
AppStorage.SetOrCreate('pub', this.pub ? '0' : "1")
})
}
}
}
3. How to prevent a custom popup from closing when the back button is pressed in HarmonyOS?
An @Entry
-decorated component can listen for back events by overriding onBackPress
.
4. When loading pages via navigation in HarmonyOS, the first secondary page on a foldable screen in full-screen mode does not display the back button?
- The primary page jumps to the secondary page via
router.pushUrl
. - The secondary page is written using
Navigation
, and navigating from the first secondary page to the second usesthis.pageInfos.pushPathByName()
.
Solution:
Navigation
uses hideBackButton
to hide the back button in the title bar. This does not support hiding the back button in the NavDestination
component's title bar.
- Default:
false
(show back button) -
true
: Hide back button. - Note: The back button only takes effect when
titleMode
isNavigationTitleMode.Mini
.
Reference document: https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/ts-basic-components-navigation-V5
5. How to achieve synchronous scaling of page layouts in HarmonyOS based on display size?
Use responsive layouts to dynamically adjust the page.
Reference: https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/responsive-layout-V5
Key points:
- Adaptive layouts ensure normal display within a certain window size range, but significant size changes (e.g., from 400vp to 1000vp) may require responsive layouts to adjust page structure.
- Responsive layouts allow elements to automatically adapt to external container changes based on specific features (e.g., window width, screen orientation).
- The most common feature is window width, divided into breakpoints. When the width crosses a breakpoint, the layout adjusts (e.g., from single-column to multi-column) for optimal display.
Top comments (0)