需求描述
我们App在Android上有一个UI是弹框中展示List列表,由于List的每个Item的高度不固定同时为了整体美观。UI做出如下要求:
- List的item小于等于2的时候高度自适应
- List的item大于2的时候,高度限制为前2个Item之和。
实现细节
- 定义list的高度为listHeight: number | string = 'auto',保证初始化时正常加载
- 为List以及ListItem定义id标签,在build()方法中对应组件直接.id()就行
- 在aboutToAppear()方法中通过inspector.createComponentObserver监听layout事件,在收到第二个item的layout完成事件之后通过componentUtils.getRectangleById方法获得2个item的高度,动态为listHeight赋值。
代码参考
const id_List = 'MultiDialogList';
const id_List_Item = 'MultiDialogListItem';
@Entry(...)
@Component
export struct MultiDialogStruct {
@LocalStorageProp(storageKey) permissions: Array<PermissionData> = new Array();
@State listHeight: number | string = 'auto';
build() {
...
List() {
ForEach(this.permissions, (item: PermissionData, index) => {
ListItem() {
...
}
.id(id_List_Item + index)
});
}
.id(id_List)
.height(this.listHeight)
...
}
listener: inspector.ComponentObserver = inspector.createComponentObserver(id_List);
listenerItem: inspector.ComponentObserver = inspector.createComponentObserver(id_List_Item + '1');
aboutToAppear() {
if (this.permissions.length > 2) {
let itemLayoutComplete: boolean = false;
//list初始化时会回调一次第一个item为0以及List的layout完成。因此需要监听下标为1也就是第二个item的layout完成
//保证正确处理高度
this.listener.on('layout', () => {
if (itemLayoutComplete) {
let itemOne: componentUtils.ComponentInfo = componentUtils.getRectangleById(id_List_Item + '0');
let itemTwo: componentUtils.ComponentInfo = componentUtils.getRectangleById(id_List_Item + '1');
if (this.listHeight == 'auto') {
this.listHeight = px2vp(itemOne.size.height + itemTwo.size.height);
}
}
});
this.listenerItem.on('layout', () => {
itemLayoutComplete = true;
});
}
}
aboutToDisappear(): void {
this.listener.off('layout');
this.listenerItem.off('layout');
}
}