1# 自定义组件的自定义布局 2<!--Kit: ArkUI--> 3<!--Subsystem: ArkUI--> 4<!--Owner: @song-song-song--> 5<!--Designer: @lanshouren--> 6<!--Tester: @liuli0427--> 7<!--Adviser: @HelloCrease--> 8 9如果需要通过测算的方式布局自定义组件内子组件的位置,建议使用以下接口: 10 11- [onMeasureSize](../../reference/apis-arkui/arkui-ts/ts-custom-component-layout.md#onmeasuresize10):组件每次布局时触发,计算子组件的尺寸,其执行时间先于onPlaceChildren。 12 13- [onPlaceChildren](../../reference/apis-arkui/arkui-ts/ts-custom-component-layout.md#onplacechildren10):组件每次布局时触发,设置子组件的起始位置。 14 15**示例:** 16 17``` 18// xxx.ets 19@Entry 20@Component 21struct Index { 22 build() { 23 Column() { 24 CustomLayout({ builder: ColumnChildren }) 25 } 26 } 27} 28 29// 通过builder的方式传递多个组件,作为自定义组件的一级子组件(即不包含容器组件,如Column) 30@Builder 31function ColumnChildren() { 32 ForEach([1, 2, 3], (index: number) => { // 暂不支持lazyForEach的写法 33 Text('S' + index) 34 .fontSize(30) 35 .width(100) 36 .height(100) 37 .borderWidth(2) 38 .offset({ x: 10, y: 20 }) 39 }) 40} 41 42@Component 43struct CustomLayout { 44 @Builder 45 doNothingBuilder() { 46 }; 47 48 @BuilderParam builder: () => void = this.doNothingBuilder; 49 @State startSize: number = 100; 50 result: SizeResult = { 51 width: 0, 52 height: 0 53 }; 54 55 // 第一步:计算各子组件的大小 56 onMeasureSize(selfLayoutInfo: GeometryInfo, children: Array<Measurable>, constraint: ConstraintSizeOptions) { 57 let size = 100; 58 children.forEach((child) => { 59 let result: MeasureResult = child.measure({ minHeight: size, minWidth: size, maxWidth: size, maxHeight: size }) 60 size += result.width / 2; 61 }) 62 // this.result在该用例中代表自定义组件本身的大小,onMeasureSize方法返回的是组件自身的尺寸。 63 this.result.width = 100; 64 this.result.height = 400; 65 return this.result; 66 } 67 // 第二步:放置各子组件的位置 68 onPlaceChildren(selfLayoutInfo: GeometryInfo, children: Array<Layoutable>, constraint: ConstraintSizeOptions) { 69 let startPos = 300; 70 children.forEach((child) => { 71 let pos = startPos - child.measureResult.height; 72 child.layout({ x: pos, y: pos }) 73 }) 74 } 75 76 build() { 77 this.builder() 78 } 79} 80``` 81 82 83 84以上示例中,Index页面包含一个实现了自定义布局的自定义组件,且对应自定义组件的子组件通过index页面内的builder方式传入。 85 86而在自定义组件中,调用了onMeasureSize和onPlaceChildren设置子组件大小和放置位置。例如,在本示例中,在onMeasureSize中初始化组件大小size=100,后续的每一个子组件size会加上上一个子组件大小的一半,实现组件大小递增的效果。而在onPlaceChildren中,定义startPos=300,设置每一个子组件的位置为startPos减去子组件自身的高度,所有子组件右下角一致在顶点位置(300,300),实现一个从右下角开始展示组件的类Stack组件。