Problem Description
How to implement a pop-up window like the one shown below so that the image goes beyond the upper border of the pop-up window.
Background Knowledge
The content style of the pop-up window popped up through the UIContext.getPromptAction().openCustomDialog() interface is displayed completely according to the style set in dialogContent.
Use the bindSheet property to bind a component to a semi-modal page. When inserting the component, you can set a custom or default built-in height to determine the semi-modal size. Use CustomBuilder with Column and Row containers to customize the display area. To display the stacking order of components within the page, set the zIndex property.
Stack is a stacking container. Subcomponents are stacked in order, and the next subcomponent covers the previous one.
Solution
For pop-ups that use @Builder to customize the constructor as UI content, there is a common method to set up the aforementioned effects. The basic idea is: set the root container component of the entire pop-up UI content to a transparent background, and place the actual visible UI content of the pop-up frame as a child component within this transparent background parent container, stacking it with an image. Part of the image is displayed on the pop-up frame with visible UI content, and part is displayed on the transparent background.
This stacking layout can be achieved using the Stack stacking layout, or by using zIndex to set the display level and margin to achieve an upward shift. Below, we will demonstrate the specific implementation of both methods using two types of pop-ups: openCustomDialog for a global custom pop-up and bindSheet for a semi-modal pop-up.
Scene 1: The openCustomDialog global custom dialog uses a Stack layout to achieve the effect of images exceeding the dialog border.
The core implementation code of the dialog is as follows:
@Builder
function customDialogBuilder(close: () => void) {
Stack() {
Column({ space: 20 }) {
Row() {
SymbolGlyph($r('sys.symbol.xmark'))
.onClick(() => {
close();
})
}
.width('100%')
.justifyContent(FlexAlign.End)
Text('Huawei').fontSize(24)
Button('Close pop-up window').onClick(() => {
close();
})
}
.borderRadius(8)
.padding(10)
.margin({ top: 50 })
.backgroundColor(Color.White)
.width('100%')
Image($r('app.media.startIcon'))
.width(100)
}
.alignContent(Alignment.Top)
.margin({ right: 20, left: 20 })
.backgroundColor(Color.Transparent)
}
The code to invoke a pop-up using UIContext.getPromptAction().openCustomDialog() is as follows:
import { ComponentContent } from '@kit.ArkUI'
@Entry
@Component
struct Page {
build() {
RelativeContainer() {
Text('Open the pop-up window')
.id('Page1HelloWorld')
.fontSize($r('app.float.page_text_font_size'))
.fontWeight(FontWeight.Bold)
.alignRules({
center: { anchor: '__container__', align: VerticalAlign.Center },
middle: { anchor: '__container__', align: HorizontalAlign.Center }
})
.onClick(() => {
let uiContext = this.getUIContext();
let contentNode = new ComponentContent(uiContext, wrapBuilder(customDialogBuilder), () => {
uiContext.getPromptAction().closeCustomDialog(contentNode);
})
uiContext.getPromptAction().openCustomDialog(contentNode)
})
}
.height('100%')
.width('100%')
}
}
The effect is as follows:
Scenario 2: BindSheet semi-modal pop-up window uses zIndex+margin to achieve the effect of the image exceeding the pop-up window border.
1.Set the bindSheet background color to transparent and hide the bindSheet's built-in close button.
.bindSheet($$this.isShow, this.myBuilder(), {
height: this.sheetHeight,
// Set the background color of bindSheet to transparent.
backgroundColor: '#00000000',
// Hide the built-in close button of bindSheet
showClose: false,
radius: LengthMetrics.vp(0),
})
2.Set the display level of the Image component to the highest level through .zIndex(2).
Image($r('app.media.startIcon'))
.width(80)
.height(80)
.clip(false)
.margin({ left: 10 })
// Set the image's layer to the highest, displaying it on the topmost level.
.zIndex(2)
3.Set the container Row to the lowest display level through .zIndex(1) and use .margin({ top: -55 }) to set the Row to offset upwards.
Row() {
Blank()
Image($r('app.media.startIcon'))
.height(25)
.width(25)
.margin({ top: 10, right: 10 })
}
// Set the image layer to the lowest level, displaying it beneath other images.
.zIndex(1)
// Set the container to offset upwards
.margin({ top: -55 })
.borderRadius({ topLeft: 20, topRight: 20 })
.width('100%')
.height(380)
.backgroundColor(Color.White)
.alignItems(VerticalAlign.Top)
.justifyContent(FlexAlign.SpaceBetween)
The complete code is as follows:
import { LengthMetrics } from '@kit.ArkUI'
@Entry
@ComponentV2
struct ListExample {
@Local isShow: boolean = false
@Local sheetHeight: number = 400
@Builder
myBuilder() {
CustomSheet()
}
build() {
Column() {
Text('Open the pop-up window')
.width('100%')
.height('100%')
.onClick(() => {
this.isShow = true;
})
.fontSize(20)
.margin(10)
.bindSheet($$this.isShow, this.myBuilder(), {
height: this.sheetHeight,
// Set the background color of bindSheet to transparent.
backgroundColor: '#00000000',
// Hide the built-in close button of bindSheet
showClose: false,
radius: LengthMetrics.vp(0),
})
}
.width('100%')
.height('100%')
.margin({ top: 50 })
}
}
@Builder
export function CustomSheet() {
Column() {
Image($r('app.media.startIcon'))
.width(80)
.height(80)
.clip(false)
.margin({ left: 10 })
// Set the image's layer to the highest, displaying it on the topmost level.
.zIndex(2)
Row() {
Blank()
Image($r('app.media.startIcon'))
.height(25)
.width(25)
.margin({ top: 10, right: 10 })
}
// Set the image layer to the lowest level, displaying it beneath other images.
.zIndex(1)
// Set the container to offset upwards
.margin({ top: -55 })
.borderRadius({ topLeft: 20, topRight: 20 })
.width('100%')
.height(380)
.backgroundColor(Color.White)
.alignItems(VerticalAlign.Top)
.justifyContent(FlexAlign.SpaceBetween)
}
.width('100%')
.height('100%')
// Set the background color of the column to transparent.
.backgroundColor('#00000000')
.justifyContent(FlexAlign.Start)
.alignItems(HorizontalAlign.Start)
}
The effect is as follows:
Verification Result
This example supports API Version 19 Release and above.
This example supports HarmonyOS 5.1.1 Release SDK and above.
This example requires DevEco Studio 5.1.1 Release and above for compilation and execution.



Top comments (0)