1# 自定义组件的自定义布局 2 3自定义组件的自定义布局用于通过数据计算的方式布局自定义组件内的子组件。 4 5>**说明:** 6> 7>- 本模块首批接口从API version 9开始支持,后续版本的新增接口,采用上角标单独标记接口的起始版本。 8 9## onPlaceChildren<sup>10+</sup> 10 11onPlaceChildren?(selfLayoutInfo: GeometryInfo, children: Array<Layoutable>, constraint: ConstraintSizeOptions):void 12 13ArkUI框架会在自定义组件布局时,将该自定义组件的子节点自身的尺寸范围通过onPlaceChildren传递给该自定义组件。不允许在onPlaceChildren函数中改变状态变量。 14 15**参数:** 16 17| 参数名 | 类型 | 说明 | 18|----------------|------------------------------------------------------------|------------------| 19| selfLayoutInfo | [GeometryInfo](#geometryinfo10) | 父组件布局信息。 | 20| children | Array<[Layoutable](#layoutable10)> | 子组件布局信息。 | 21| constraint | [ConstraintSizeOptions](ts-types.md#constraintsizeoptions) | 父组件constraint信息。 | 22 23## onMeasureSize<sup>10+</sup> 24 25onMeasureSize?(selfLayoutInfo: GeometryInfo, children: Array<Measurable>, constraint: ConstraintSizeOptions):[SizeResult](#sizeresult10) 26 27ArkUI框架会在自定义组件确定尺寸时,将该自定义组件的节点信息和尺寸范围通过onMeasureSize传递给该开发者。不允许在onMeasureSize函数中改变状态变量。 28 29**参数:** 30 31| 参数名 | 类型 | 说明 | 32|----------------|------------------------------------------------------------|------------------| 33| selfLayoutInfo | [GeometryInfo](#geometryinfo10) | 父组件布局信息。 | 34| children | Array<[Measurable](#measurable10)> | 子组件布局信息。 | 35| constraint | [ConstraintSizeOptions](ts-types.md#constraintsizeoptions) | 父组件constraint信息。 | 36 37## GeometryInfo<sup>10+</sup> 38 39父组件布局信息。 40 41| 属性 | 属性类型 | 描述 | 42|-------------|-----------|---------------------| 43| borderWidth | [EdgeWidth](ts-types.md#edgewidths9) | 父组件边框宽度。<br>单位:vp | 44| margin | [Margin](ts-types.md#margin) | 父组件margin信息。 <br>单位:vp | 45| padding | [Padding](ts-types.md#padding) | 父组件padding信息。<br>单位:vp | 46| width | number | 测量后的宽。<br>单位:vp<br> **说明:** <br>若值为空时,则返回组件的百分比宽。 | 47| height | number | 测量后的高。<br>单位:vp<br> **说明:** <br>若值为空时,则返回组件的百分比高。 | 48 49 50## Layoutable<sup>10+</sup> 51 52子组件布局信息。 53 54| 属性 | 属性类型 | 描述 | 55|------------|---------------------------------------------------------|---------------------| 56| measureResult| [MeasureResult](#measureresult10) | 子组件测量后的尺寸信息。 <br>单位:vp | 57| layout | (position: [Position](ts-types.md#position8)) => void | 调用此方法对子组件的位置信息进行限制。 | 58 59## Measurable<sup>10+</sup> 60 61子组件位置信息。 62 63| 属性 | 属性类型 | 描述 | 64|------------|----------------------------------------------------------------------------------|---------------------------------------| 65| measure | (childConstraint: [ConstraintSizeOptions](ts-types.md#constraintsizeoptions)) => [MeasureResult](#measureresult10) | 调用此方法对子组件的尺寸范围进行限制。<br/>返回值:子组件测量后的尺寸。 | 66 67## MeasureResult<sup>10+</sup> 68 69测量后的组件布局信息。 70 71| 属性 | 属性类型 | 描述 | 72|--------|--------|-------| 73| width | number | 测量后的宽。<br>单位:vp | 74| height | number | 测量后的高。<br>单位:vp | 75 76 77## SizeResult<sup>10+</sup> 78 79组件尺寸信息。 80 81| 属性 | 属性类型 | 描述 | 82|--------|--------|-------| 83| width | number | 测量后的宽。<br>单位:vp | 84| height | number | 测量后的高。<br>单位:vp | 85 86> **说明:** 87> 88>- 自定义布局暂不支持LazyForEach写法。 89>- 使用builder形式的自定义布局创建,自定义组件的build()方法内只允许存在this.builder(),即示例的推荐用法。 90>- 父容器(自定义组件)上设置的尺寸信息,除aspectRatio之外,优先级小于onMeasureSize设置的尺寸信息。 91>- 子组件设置的位置信息,offset、position、markAnchor优先级大于onPlaceChildren设置的位置信息,其他位置设置属性不生效。 92>- 使用自定义布局方法时,需要同时调用onMeasureSize和onPlaceChildren方法,否则可能出现布局异常。 93 94``` 95// xxx.ets 96@Entry 97@Component 98struct Index { 99 build() { 100 Column() { 101 CustomLayout({ builder: ColumnChildren }) 102 } 103 } 104} 105 106@Builder 107function ColumnChildren() { 108 ForEach([1, 2, 3], (index: number) => { //暂不支持lazyForEach的写法 109 Text('S' + index) 110 .fontSize(30) 111 .width(100) 112 .height(100) 113 .borderWidth(2) 114 .offset({ x: 10, y: 20 }) 115 }) 116} 117 118@Component 119struct CustomLayout { 120 @Builder 121 doNothingBuilder() { 122 }; 123 124 @BuilderParam builder: () => void = this.doNothingBuilder; 125 @State startSize: number = 100; 126 result: SizeResult = { 127 width: 0, 128 height: 0 129 }; 130 131 onPlaceChildren(selfLayoutInfo: GeometryInfo, children: Array<Layoutable>, constraint: ConstraintSizeOptions) { 132 let startPos = 300; 133 children.forEach((child) => { 134 let pos = startPos - child.measureResult.height; 135 child.layout({ x: pos, y: pos }) 136 }) 137 } 138 139 onMeasureSize(selfLayoutInfo: GeometryInfo, children: Array<Measurable>, constraint: ConstraintSizeOptions) { 140 let size = 100; 141 children.forEach((child) => { 142 let result: MeasureResult = child.measure({ minHeight: size, minWidth: size, maxWidth: size, maxHeight: size }) 143 size += result.width / 2 144 ; 145 }) 146 this.result.width = 100; 147 this.result.height = 400; 148 return this.result; 149 } 150 151 build() { 152 this.builder() 153 } 154} 155``` 156 157 158 159## onLayout<sup>(deprecated)</sup> 160 161onLayout?(children: Array<LayoutChild>, constraint: ConstraintSizeOptions): void 162 163ArkUI框架会在自定义组件布局时,将该自定义组件的子节点信息和自身的尺寸范围通过onLayout传递给该自定义组件。不允许在onLayout函数中改变状态变量。 164 165该接口从API version 9开始支持,从API version 10开始废弃,推荐使用[onPlaceChildren](#onplacechildren10)替代。 166 167**参数:** 168 169| 参数名 | 类型 | 说明 | 170|------------|------------------------------------------------------------|------------------| 171| children | Array<[LayoutChild](#layoutchilddeprecated)> | 子组件布局信息。 | 172| constraint | [ConstraintSizeOptions](ts-types.md#constraintsizeoptions) | 父组件constraint信息。 | 173 174## onMeasure<sup>(deprecated)</sup> 175 176onMeasure?(children: Array<LayoutChild>, constraint: ConstraintSizeOptions): void 177 178ArkUI框架会在自定义组件确定尺寸时,将该自定义组件的子节点信息和自身的尺寸范围通过onMeasure传递给该自定义组件。不允许在onMeasure函数中改变状态变量。 179 180该接口从API version 9开始支持,从API version 10开始废弃,推荐使用[onMeasureSize](#onmeasuresize10)替代。 181 182**参数:** 183 184| 参数名 | 类型 | 说明 | 185|------------|------------------------------------------------------------|------------------| 186| children | Array<[LayoutChild](#layoutchilddeprecated)> | 子组件布局信息。 | 187| constraint | [ConstraintSizeOptions](ts-types.md#constraintsizeoptions) | 父组件constraint信息。 | 188 189## LayoutChild<sup>(deprecated)</sup> 190 191子组件布局信息。 192 193从API version 9开始,从API version 10开始废弃,该接口支持在ArkTS卡片中使用。 194 195 196| 属性 | 属性类型 | 描述 | 197|------------|--------------------------------------------------------------------|---------------------| 198| name | string | 子组件名称。 | 199| id | string | 子组件id。 | 200| constraint | [ConstraintSizeOptions](ts-types.md#constraintsizeoptions) | 子组件约束尺寸。 | 201| borderInfo | [LayoutBorderInfo](#layoutborderinfodeprecated) | 子组件border信息。 | 202| position | [Position](ts-types.md#position8) | 子组件位置坐标。 | 203| measure | (childConstraint: [ConstraintSizeOptions](ts-types.md#constraintsizeoptions)) => void | 调用此方法对子组件的尺寸范围进行限制。 | 204| layout | (LayoutInfo: [LayoutInfo](#layoutinfodeprecated)) => void | 调用此方法对子组件的位置信息进行限制。 | 205 206## LayoutBorderInfo<sup>(deprecated)</sup> 207 208子组件border信息。 209 210从API version 9开始,从API version 10开始废弃,该接口支持在ArkTS卡片中使用。 211 212| 属性 | 属性类型 | 描述 | 213|-------------|--------------------------------------|-------------------------| 214| borderWidth | [EdgeWidths](ts-types.md#edgewidths9) | 边框宽度类型,用于描述组件边框不同方向的宽度。 | 215| margin | [Margin](ts-types.md#margin) | 外边距类型,用于描述组件不同方向的外边距。 | 216| padding | [Padding](ts-types.md#padding) | 内边距类型,用于描述组件不同方向的内边距。 | 217 218## LayoutInfo<sup>(deprecated)</sup> 219 220子组件layout信息。 221 222从API version 9开始,从API version 10开始废弃,该接口支持在ArkTS卡片中使用。 223 224| 属性 | 属性类型 | 描述 | 225|------------|------------------------------------------------------------|----------| 226| position | [Position](ts-types.md#position8) | 子组件位置坐标。 | 227| constraint | [ConstraintSizeOptions](ts-types.md#constraintsizeoptions) | 子组件约束尺寸。 | 228 229```ts 230// xxx.ets 231@Entry 232@Component 233struct Index { 234 build() { 235 Column() { 236 CustomLayout() { 237 ForEach([1, 2, 3], (index: number) => { 238 Text('Sub' + index) 239 .fontSize(30) 240 .borderWidth(2) 241 }) 242 } 243 } 244 } 245} 246 247 248@Component 249struct CustomLayout { 250 @Builder 251 doNothingBuilder() { 252 }; 253 254 @BuilderParam builder: () => void = this.doNothingBuilder; 255 256 onLayout(children: Array<LayoutChild>, constraint: ConstraintSizeOptions) { 257 let pos = 0; 258 children.forEach((child) => { 259 child.layout({ position: { x: pos, y: pos }, constraint: constraint }) 260 pos += 70; 261 }) 262 } 263 264 onMeasure(children: Array<LayoutChild>, constraint: ConstraintSizeOptions) { 265 let size = 100; 266 children.forEach((child) => { 267 child.measure({ minHeight: size, minWidth: size, maxWidth: size, maxHeight: size }) 268 size += 50; 269 }) 270 } 271 272 build() { 273 this.builder() 274 } 275} 276``` 277 278