DEV Community

HarmonyOS
HarmonyOS

Posted on

Implementing child components to adapt to the height of the tallest child component

Read the original article:Implementing child components to adapt to the height of the tallest child component

Implementing child components to adapt to the height of the tallest child component

Requirement Description

In the parent component, there are multiple child components with different heights. The goal is to make the heights of all child components consistent with the height of the tallest child component.

Background Knowledge

The Row component is a container in ArkUI that arranges its children horizontally. Currently, there is no direct API available to automatically adjust the heights of all child components to match the tallest child component. However, this can be achieved by getting the height of the tallest child component and assigning this height to the other child components:

  • The onAreaChange event triggers when the component's area changes. It responds only to changes in the size or position of the component due to layout changes. You can use this event to get the height of the component. For usage details, refer to the onAreaChange example.
  • The onSizeChange event triggers when the component's size changes. It responds only to size changes caused by layout changes, but not to changes in rendering properties such as translate or offset. For usage details, refer to the onSizeChange example.

Implementation Steps

Given multiple child components with inconsistent heights, if the parent component does not have a height constraint set, the parent component will automatically adjust to the height of the tallest child component:

  • Using the onAreaChange event
  • Using a ForEach loop for rendering

Code Snippet

Plan 1: Use the callback of onAreaChange to get the newValue's height and directly assign it.

@Entry
@Component
struct Index {
  @State subHeight: Length = 0

  build() {
    Row() {
      Column() {
        Text('I am Text 1')
        Text('I am Text 2')
      }
      .backgroundColor('#ff6c7343')
      .height(this.subHeight == 0 ? 'auto' : this.subHeight)

      Column() {
        Text('I am Text 1')
        Text('I am Text 2')
        Text('I am Text 3')
      }
      .backgroundColor('#ff347e74')
      .height(this.subHeight == 0 ? 'auto' : this.subHeight)

      Column() {
        Text('I am Text 1')
        Text('I am Text 2')
        Text('I am Text 3')
        Text('I am Text 4')
      }
      .backgroundColor('#ff3a63a2')
      .height(this.subHeight === 0 ? 'auto' : this.subHeight)
    }
    .backgroundColor(Color.Pink)
    .onAreaChange((oldValue: Area, newValue: Area) => {
      this.subHeight = newValue.height
    })
  }
}
Enter fullscreen mode Exit fullscreen mode

Plan 2: Use a ForEach loop for rendering. This plan abstracts each child component into a class, optimizing the input method in aboutToAppear for easier later development and maintenance.

class TextClass {
  name: string[] = []
  color: string = ''
  index: number = 0
}

@Entry
@Component
struct Index {
  @State textList: TextClass[] = []
  @State subHeight: Length = 0

  aboutToAppear(): void {
    let brother1 = new TextClass()
    brother1.index = 0
    brother1.color = '#ff6c7343'
    brother1.name = ['I am Text 1', 'I am Text 2']
    this.textList.push(brother1)
    let brother2 = new TextClass()
    brother2.index = 1
    brother2.color = '#ff347e74'
    brother2.name = ['I am Text 1', 'I am Text 2', 'I am Text 3']
    this.textList.push(brother2)
    let brother3 = new TextClass()
    brother3.index = 2
    brother3.color = '#ff3a63a2'
    brother3.name = ['I am Text 1', 'I am Text 2', 'I am Text 3', 'I am Text 4']
    this.textList.push(brother3)
  }

  build() {
    Row() {
      ForEach(this.textList, (item: TextClass, index: number) => {
        Column() {
          ForEach(item.name, (text: string, index2: number) => {
            Text(text)
              .fontSize('16fp')
          })
        }
        .backgroundColor(item.color)
        .height(this.subHeight === 0 ? 'auto' : this.subHeight)
      })
    }
    .backgroundColor(Color.Pink)
    .onAreaChange((oldValue: Area, newValue: Area) => {
      this.subHeight = newValue.height
    })
  }
}
Enter fullscreen mode Exit fullscreen mode

Using the onSizeChange event: The usage is the same as onAreaChange. The two plans can be modified as follows:

struct Index {
  @State subHeight: Length | undefined = 0
  // ...

  build() {
    Row() {
     // ...
    }
    // ...
    .onSizeChange((oldValue: SizeOptions, newValue: SizeOptions) => {
      this.subHeight = newValue.height
    })
  }
}
Enter fullscreen mode Exit fullscreen mode

Test Results

c1.png

Written by Bunyamin Eymen Alagoz

Top comments (0)