Problem Description
When using bindSheet with SheetSize.FIT_CONTENT to adapt the content height, the maximum height of the semi-modal page can only be the system-defined value and cannot be customized. How can the height be set based on the content of the semi-modal page, while requiring the maximum height to be set as a percentage, for example, setting it to 80%?
Problem code:
@Entry
@Component
struct SheetDemo {
@State isShowSheet: boolean = false
private items : number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
@Builder
SheetBuilder() {
Column() {
List({space:'10vp'}) {
ForEach(this.items,(item : number) => {
ListItem() {
Text(String(item)).fontSize(16).fontWeight(FontWeight.Bold)
}.width('90%').height('80vp').backgroundColor('#ff53ecd9').borderRadius(10)
})
}.alignListItem(ListItemAlign.Center).margin({top:'10vp'}).width('100%')
}
.width('90%')
.height('100%')
// .height('10%') // Cannot take effect and the interface jumps
// .constraintSize({maxHeight:'20%'}) // Cannot take effect and the interface jumps
}
build() {
Column() {
Button('Open Sheet').width('90%').height('80vp')
.onClick(()=>{
this.isShowSheet = !this.isShowSheet
})
.bindSheet($$this.isShowSheet,this.SheetBuilder(), {
height: SheetSize.FIT_CONTENT,
showClose: false,
preferType: SheetType.BOTTOM,
})
}.width('100%').height('100%')
.justifyContent(FlexAlign.Center)
}
}
Background Knowledge
Semi-modal transition: Bind a semi-modal page to a component using the bindSheet property. When the component is inserted, you can determine the size of the semi-modal by setting a custom or default built-in height.
Solution
Calculate the proportion of the semi-modal page content height in the window height. If the height exceeds the maximum height, display the maximum height and configure the height in SheetOptions:
import { window } from '@kit.ArkUI'
@Entry
@Component
struct SheetDemo {
@State sheetHeight: string = '80%'
@State windowHeight: number = 0
@State isShowSheet: boolean = false
private items : number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
private itemHeight: number = 80
private spaceHeight: number = 10
private maxHeightPercent: number = 80
@Builder
SheetBuilder() {
Column() {
List({space:this.spaceHeight}) {
ForEach(this.items,(item : number) => {
ListItem() {
Text(String(item)).fontSize(16).fontWeight(FontWeight.Bold)
}.width('90%').height(this.itemHeight).backgroundColor('#ff53ecd9').borderRadius(10)
})
}.alignListItem(ListItemAlign.Center).margin({top:'10vp'}).width('100%')
}
.width('90%')
.height('100%')
}
// Set the height according to the List content, and require the maximum height to be less than 80%
build() {
Column() {
Button('Open Sheet').width('90%').height('80vp')
.onClick(()=>{
this.isShowSheet = !this.isShowSheet
// Calculate the height ratio of elements in the List component in the window
let height: number = ((this.itemHeight+this.spaceHeight)*this.items.length + this.spaceHeight)/this.windowHeight * 100
this.sheetHeight = `${Math.min(this.maxHeightPercent, height)}%`
})
.bindSheet($$this.isShowSheet,this.SheetBuilder(), {
height: this.sheetHeight, // this.sheetHeight is a percentage of string type
showClose: false,
preferType: SheetType.BOTTOM,
})
}.width('100%').height('100%')
.justifyContent(FlexAlign.Center)
}
onPageShow(): void {
let windowClass: window.Window | undefined = undefined;
window.getLastWindow(getContext()).then((data)=> {
windowClass = data;
try {
let properties = windowClass.getWindowProperties();
let rect = properties.windowRect;
// rect.width: window width; rect.height: window height. Unit: px.
this.windowHeight = px2vp(rect.height)
} catch (exception) {
console.error(`Failed to obtain the window properties. Cause code: ${exception.code}, message: ${exception.message}`);
}
})
}
}
When the list height exceeds the maximum height, the effect is as shown below:
When the list height is less than the maximum height, the effect is as shown below:


Top comments (0)