Context
When multiple ListItems appear in the same row, the text inside each ListItem may have different heights, leading to inconsistent row heights.
Since the text length is uncertain, it is not possible to fix the height of ListItem using a static height attribute.
-
Expected behavior: All
ListItems in the same row should have equal height. - Current issue: Text length varies, causing inconsistent heights.
Description
-
List: A list component containing items with equal width. It supports multiple columns and allows area changes to be captured using
onAreaChange(e.g., height updates). -
Flex: A flexible container that supports multi-row and multi-column layouts by adjusting
FlexOptions.wrapandalignItems. This allows children to stretch and fill space across the cross-axis.
Solution / Approach
Approach 1: Use Flex Container
Use a Flex container with wrap and alignItems: Stretch. This ensures items automatically align in multiple rows/columns, with each child stretched in height for consistency.
Flex({
justifyContent: FlexAlign.Center,
wrap: FlexWrap.Wrap, // Multi-line/column arrangement
alignItems: ItemAlign.Stretch, // Stretch across cross-axis
space: { cross: { value: 14, unit: LengthUnit.VP } }
}) {
ForEach(this.arr, (item: Area) => {
Column() {
TextComponentOne({ content: item.name })
}
.justifyContent(FlexAlign.Center)
.width('33%')
.border({ width: 1, radius: 7 })
})
}
Approach 2: Calculate Max Height per Row
Use onAreaChange to collect the height of each ListItem.
- For each row, compute the maximum height.
- Update all items in the row to match the max height.
- Use a state variable (
isBoolean) andif/elseto trigger layout refresh.
Steps:
- Step 1: Sort and find maximum height.
sortReturnMax(nums: number[]): number {
for (let i = 0; i < nums.length; i++) {
for (let j = 0; j < nums.length - 1 - i; j++) {
if (nums[j] > nums[j + 1]) {
const tmp = nums[j];
nums[j] = nums[j + 1];
nums[j + 1] = tmp;
}
}
}
return nums[nums.length-1]
}
- Step 2: Reset each row’s items to maximum height.
reSetHeightSize() {
for (let i = 0; i < this.arr.length; i += 3) {
let arrTmp: number[] = [this.arr[i].heightSize, this.arr[i+1].heightSize, this.arr[i+2].heightSize];
let maxHeight = this.sortReturnMax(arrTmp);
this.arr[i].heightSize = maxHeight;
this.arr[i + 1].heightSize = maxHeight;
this.arr[i + 2].heightSize = maxHeight;
}
}
- Step 3: Re-render List Items Using Updated Heights
@Builder
ListItemSameHeight() {
List({ space: 14 }) {
ForEach(this.arr, (item: Region, index: number) => {
ListItem() {
// Set the height of each ListItem to the maximum height calculated for that row
TextComponentTwo({ content: item.name, hgt: item.heightSize })
}
}, (item: Region) => JSON.stringify(item))
}
.lanes(3) // Ensure three columns per row
}
-
Step 4: Conditional Rendering Based on
isBooleanState
build() {
Column() {
if (this.isBoolean) {
// First layout: When isBoolean is true, trigger onAreaChange callback to collect and calculate ListItem heights
this.ListItemChangeRegion()
} else {
// After isBoolean changes to false, re-render the layout.
// At this stage, each ListItem's height is already set to the maximum height of its row.
this.ListItemSameHeight()
}
}
.width('100%')
.height('100%')
.padding({ top: 5 })
}
Additional Resources
https://developer.huawei.com/consumer/en/doc/harmonyos-references/ts-container-listitem#listitem10
Top comments (0)