DEV Community

HarmonyOS
HarmonyOS

Posted on

How to set the semi-modal window height to be adaptive and customize the maximum height

Read the original article:How to set the semi-modal window height to be adaptive and customize the maximum height

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)
  }
}
Enter fullscreen mode Exit fullscreen mode

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}`);
      }
    })
  }
}
Enter fullscreen mode Exit fullscreen mode

When the list height exceeds the maximum height, the effect is as shown below:

kvbbc.gif

When the list height is less than the maximum height, the effect is as shown below:

cke_5386.png

Written by Mucahid Kincir

Top comments (0)