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> **说明:** 12> 13> 本模块首批接口从API version 9开始支持,后续版本的新增接口,采用上角标单独标记接口的起始版本。 14> 15> 在自定义组件内实现onMeasureSize, onPlaceChildren任一方法即视为实现自定义布局,推荐同时实现两种方法,具体参数说明可见对应接口参数说明。 16> 17> 从API version 20开始,在自定义布局的自定义组件中,子组件若设置了[LayoutPolicy](./ts-universal-attributes-size.md#layoutpolicy15)对象的fixAtIdealSize属性,表示尺寸将不受父组件约束,完全按照开发者自定义的尺寸范围布局。 18> 19> 自定义布局内不支持使用懒加载(包含[Repeat](../../../ui/state-management/arkts-new-rendering-control-repeat.md)和[LazyForEach](../../../ui/state-management/arkts-rendering-control-lazyforeach.md))。 20 21## onMeasureSize<sup>10+</sup> 22 23onMeasureSize?(selfLayoutInfo: GeometryInfo, children: Array<Measurable>, constraint: ConstraintSizeOptions): SizeResult 24 25ArkUI框架会在自定义组件确定尺寸时,将该自定义组件的节点信息和尺寸范围通过onMeasureSize传递给该开发者。不允许在onMeasureSize函数中改变状态变量。 26 27**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 28 29**系统能力:** SystemCapability.ArkUI.ArkUI.Full 30 31**参数:** 32 33| 参数名 | 类型 | 必填|说明 | 34| -------------- | ---------------------------------------------------------- | ---|------------------------------------------------------------ | 35| selfLayoutInfo | [GeometryInfo](#geometryinfo10) | 是|计算自定义组件大小后的自身布局信息。 <br/>**说明:** <br/>第一次布局时以自身设置的属性为准。 | 36| children | Array<[Measurable](#measurable10)> | 是|计算子组件大小后的子组件布局信息。<br/>**说明:** <br/>如果没有设置子组件的布局信息,子组件会维持上一次的布局信息,当子组件从来没有设置过尺寸时,尺寸默认为0。 | 37| constraint | [ConstraintSizeOptions](ts-types.md#constraintsizeoptions) | 是|自定义组件的布局约束信息。 | 38 39**返回值:** 40 41| 类型 | 说明 | 42| --------------------------- | -------------- | 43| [SizeResult](#sizeresult10) | 组件尺寸信息。 | 44 45## onPlaceChildren<sup>10+</sup> 46 47onPlaceChildren?(selfLayoutInfo: GeometryInfo, children: Array<Layoutable>, constraint: ConstraintSizeOptions):void 48 49ArkUI框架会在自定义组件确定位置时,将该自定义组件的子节点自身的尺寸范围通过onPlaceChildren传递给该自定义组件。不允许在onPlaceChildren函数中改变状态变量。 50 51**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 52 53**系统能力:** SystemCapability.ArkUI.ArkUI.Full 54 55**参数:** 56 57| 参数名 | 类型 |必填| 说明 | 58|----------------|------------------------------------------------------------|---|------------------| 59| selfLayoutInfo | [GeometryInfo](#geometryinfo10) |是 |计算父组件(自定义组件)后的自身布局信息。 | 60| children | Array<[Layoutable](#layoutable10)> |是 |计算子组件大小后的子组件布局信息。 | 61| constraint | [ConstraintSizeOptions](ts-types.md#constraintsizeoptions) |是 |自定义组件的布局约束信息。 | 62 63**示例:** 64 65示例请参考[自定义布局代码示例](#示例)。 66 67## GeometryInfo<sup>10+</sup> 68 69父组件(自定义组件)布局信息,继承自[SizeResult](#sizeresult10)。 70 71**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 72 73**系统能力:** SystemCapability.ArkUI.ArkUI.Full 74 75| 名称 | 类型 | 只读 | 可选 | 说明 | 76| -------- | -------- | -------- | -------- | -------- | 77| borderWidth | [EdgeWidth](ts-types.md#edgewidths9) |否|否| 父组件(自定义组件)边框宽度。<br>单位:vp。 | 78| margin | [Margin](ts-types.md#margin) | 否|否|父组件(自定义组件)margin信息。 <br>单位:vp。 | 79| padding | [Padding](ts-types.md#padding) |否|否| 父组件(自定义组件)padding信息。<br>单位:vp。 | 80 81## Layoutable<sup>10+</sup> 82 83子组件布局信息。 84 85**系统能力:** SystemCapability.ArkUI.ArkUI.Full 86 87### 属性 88 89| 名称 | 类型 | 只读|可选| 说明 | 90|--------------|---------------------------------- | ------|-----------------------------------------------------|---------------------| 91| measureResult| [MeasureResult](#measureresult10) | 否|否| 子组件测量后的尺寸信息。<br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。<br>单位:vp | 92| uniqueId<sup>18+</sup>| number | 否 |是| 系统为子组件分配的唯一标识UniqueID。<br>取值范围[0,+∞)。<br/>**原子化服务API:** 从API version 18开始,该接口支持在原子化服务中使用。| 93 94### layout 95 96layout(position: Position) : void 97 98调用此方法对子组件的位置信息进行限制。 99 100**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 101 102**系统能力:** SystemCapability.ArkUI.ArkUI.Full 103 104**参数:** 105 106| 参数名 | 类型 | 必填 |说明 | 107|-----------------|---------------------------------------------------------|---------------------|-------------| 108| position | [Position](ts-types.md#position) | 是 | 绝对位置。 | 109 110### getMargin<sup>12+</sup> 111 112getMargin() : DirectionalEdgesT\<number> 113 114调用此方法获取子组件的margin信息。 115 116**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 117 118**系统能力:** SystemCapability.ArkUI.ArkUI.Full 119 120**返回值:** 121 122| 类型 | 说明 | 123|------------------------------------|---------------------------------------------| 124| [DirectionalEdgesT<number>](./ts-types.md#directionaledgestt12) | 子组件的margin信息。 | 125 126 ### getPadding<sup>12+</sup> 127 128getPadding() : DirectionalEdgesT\<number> 129 130 调用此方法获取子组件的padding信息。 131 132**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 133 134**系统能力:** SystemCapability.ArkUI.ArkUI.Full 135 136 **返回值:** 137 138| 类型 | 说明 | 139|------------------------------------|---------------------------------------------| 140| [DirectionalEdgesT<number>](./ts-types.md#directionaledgestt12) | 子组件的padding信息。 | 141 142### getBorderWidth<sup>12+</sup> 143 144getBorderWidth() : DirectionalEdgesT\<number> 145 146调用此方法获取子组件的borderWidth信息。 147 148**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 149 150**系统能力:** SystemCapability.ArkUI.ArkUI.Full 151 152**返回值:** 153 154| 类型 | 说明 | 155|------------------------------------|---------------------------------------------| 156| [DirectionalEdgesT<number>](./ts-types.md#directionaledgestt12) | 子组件的borderWidth信息。 | 157 158## Measurable<sup>10+</sup> 159 160子组件位置信息。 161 162**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 163 164**系统能力:** SystemCapability.ArkUI.ArkUI.Full 165 166### 属性 167 168**原子化服务API:** 从API version 18开始,该接口支持在原子化服务中使用。 169 170**系统能力:** SystemCapability.ArkUI.ArkUI.Full 171 172| 名称 | 类型 | 只读 | 可选 | 说明 | 173| -------- | -------- | -------- | -------- | -------- | 174| uniqueId<sup>18+</sup>| number | 否 | 是 | 系统为子组件分配的唯一标识UniqueID。| 175 176### measure 177 178 measure(constraint: ConstraintSizeOptions) : MeasureResult 179 180 调用此方法限制子组件的尺寸范围。 181 182 **原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 183 184 **系统能力:** SystemCapability.ArkUI.ArkUI.Full 185 186 187**参数:** 188 189| 参数名 | 类型 | 必填 |说明 | 190|-----------------|---------------------------------------------------------|---------------------|-------------| 191| constraint | [ConstraintSizeOptions](ts-types.md#constraintsizeoptions) | 是 | 约束尺寸。 | 192 193**返回值:** 194 195 | 类型 | 说明 | 196 |------------------------------------|-------------------------| 197 |[MeasureResult](#measureresult10) | 测量后的组件布局信息。 | 198 199 ### getMargin<sup>12+</sup> 200 201 getMargin() : DirectionalEdgesT\<number\> 202 203 获取子组件的margin信息。 204 205**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 206 207**系统能力:** SystemCapability.ArkUI.ArkUI.Full 208 209**返回值:** 210 211 | 类型 | 说明 | 212 |------------------------------------|-------------------------| 213 |[DirectionalEdgesT<number>](./ts-types.md#directionaledgestt12) | 子组件的margin信息。 | 214 215### getPadding<sup>12+</sup> 216 217getPadding() : DirectionalEdgesT\<number\> 218 219获取子组件的padding信息。 220 221**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 222 223**系统能力:** SystemCapability.ArkUI.ArkUI.Full 224 225**返回值:** 226 227 | 类型 | 说明 | 228 |------------------------------------|-------------------------| 229 |[DirectionalEdgesT<number>](./ts-types.md#directionaledgestt12) | 子组件的padding信息。 | 230 231 ### getBorderWidth<sup>12+</sup> 232 233getBorderWidth() : DirectionalEdgesT\<number\> 234 235获取子组件的borderWidth信息。 236 237**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 238 239**系统能力:** SystemCapability.ArkUI.ArkUI.Full 240 241**返回值:** 242 243 | 类型 | 说明 | 244 |------------------------------------|-------------------------| 245 |[DirectionalEdgesT<number>](./ts-types.md#directionaledgestt12) | 子组件的borderWidth信息。| 246 247 248## MeasureResult<sup>10+</sup> 249 250测量后的组件布局信息。继承自[SizeResult](#sizeresult10)。 251 252**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 253 254**系统能力:** SystemCapability.ArkUI.ArkUI.Full 255 256## SizeResult<sup>10+</sup> 257 258组件尺寸信息。 259 260**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 261 262**系统能力:** SystemCapability.ArkUI.ArkUI.Full 263 264| 名称 | 类型 |只读|可选| 说明 | 265|--------|--------|------|------|-------| 266| width | number | 否|否|测量后的宽。<br>单位:vp。 | 267| height | number | 否|否|测量后的高。<br>单位:vp。 | 268 269> **说明:** 270> 271>- 自定义布局暂不支持LazyForEach写法。 272>- 使用builder形式的自定义布局创建,自定义组件的build()方法内只允许存在this.builder(),即示例的推荐用法。 273>- 父容器(自定义组件)上设置的尺寸信息,除aspectRatio之外,优先级小于onMeasureSize设置的尺寸信息。 274>- 子组件设置的位置信息,offset、position、markAnchor优先级大于onPlaceChildren设置的位置信息,其他位置设置属性不生效。 275>- 使用自定义布局方法时,需要同时调用onMeasureSize和onPlaceChildren方法,否则可能出现布局异常。 276 277## onLayout<sup>(deprecated)</sup> 278 279onLayout?(children: Array<LayoutChild>, constraint: ConstraintSizeOptions): void 280 281ArkUI框架会在自定义组件布局时,将该自定义组件的子节点信息和自身的尺寸范围通过onLayout传递给该自定义组件。不允许在onLayout函数中改变状态变量。 282 283该接口从API version 9开始支持,从API version 10开始废弃,推荐使用[onPlaceChildren](#onplacechildren10)替代。 284 285**卡片能力:** 从API version 9开始,该接口支持在ArkTS卡片中使用。 286 287**系统能力:** SystemCapability.ArkUI.ArkUI.Full 288 289**参数:** 290 291| 参数名 | 类型 | 必填|说明 | 292|------------|------------------------------------------------------------|------|------------------| 293| children | Array<[LayoutChild](#layoutchilddeprecated)> | 是 | 子组件布局信息。 | 294| constraint | [ConstraintSizeOptions](ts-types.md#constraintsizeoptions) | 是 |父组件constraint信息。 | 295 296## onMeasure<sup>(deprecated)</sup> 297 298onMeasure?(children: Array<LayoutChild>, constraint: ConstraintSizeOptions): void 299 300ArkUI框架会在自定义组件确定尺寸时,将该自定义组件的子节点信息和自身的尺寸范围通过onMeasure传递给该自定义组件。不允许在onMeasure函数中改变状态变量。 301 302该接口从API version 9开始支持,从API version 10开始废弃,推荐使用[onMeasureSize](#onmeasuresize10)替代。 303 304**卡片能力:** 从API version 9开始,该接口支持在ArkTS卡片中使用。 305 306**系统能力:** SystemCapability.ArkUI.ArkUI.Full 307 308**参数:** 309 310| 参数名 | 类型 |必填| 说明 | 311|------------|------------------------------------------------------------|------|------------------| 312| children | Array<[LayoutChild](#layoutchilddeprecated)> | 是 |子组件布局信息。 | 313| constraint | [ConstraintSizeOptions](ts-types.md#constraintsizeoptions) | 是 |父组件constraint信息。 | 314 315## LayoutChild<sup>(deprecated)</sup> 316 317子组件布局信息。 318 319从API version 9开始,从API version 10开始废弃,该接口支持在ArkTS卡片中使用。 320 321**卡片能力:** 从API version 9开始,该接口支持在ArkTS卡片中使用。 322 323**系统能力:** SystemCapability.ArkUI.ArkUI.Full 324 325| 名称 | 类型 | 只读|可选|说明 | 326| ---------- | ------------------------------------------------------------ | ------|------|-------------------------------------- | 327| name | string | 否|否|子组件名称。 | 328| id | string | 否|否|子组件id。 | 329| constraint | [ConstraintSizeOptions](ts-types.md#constraintsizeoptions) | 否|否|子组件约束尺寸。 | 330| borderInfo | [LayoutBorderInfo](#layoutborderinfodeprecated) | 否|否|子组件border信息。 | 331| position | [Position](ts-types.md#position) | 否|否|子组件位置坐标。 | 332| measure | (childConstraint: [ConstraintSizeOptions](ts-types.md#constraintsizeoptions)) |否|否| 调用此方法对子组件的尺寸范围进行限制。 | 333| layout | (childLayoutInfo: [LayoutInfo](#layoutinfodeprecated)) | 否|否|调用此方法对子组件的位置信息进行限制。 | 334 335## LayoutBorderInfo<sup>(deprecated)</sup> 336 337子组件border信息。 338 339从API version 9开始,从API version 10开始废弃,该接口支持在ArkTS卡片中使用。 340 341**卡片能力:** 从API version 9开始,该接口支持在ArkTS卡片中使用。 342 343**系统能力:** SystemCapability.ArkUI.ArkUI.Full 344 345| 名称 | 类型 | 只读 | 可选 | 说明 | 346| -------- | -------- | -------- | -------- | -------- | 347| borderWidth | [EdgeWidths](ts-types.md#edgewidths9) | 否|否|边框宽度类型,用于描述组件边框不同方向的宽度。 | 348| margin | [Margin](ts-types.md#margin) | 否|否|外边距类型,用于描述组件不同方向的外边距。 | 349| padding | [Padding](ts-types.md#padding) | 否|否|内边距类型,用于描述组件不同方向的内边距。 | 350 351## LayoutInfo<sup>(deprecated)</sup> 352 353子组件layout信息。 354 355从API version 9开始,从API version 10开始废弃,该接口支持在ArkTS卡片中使用。 356 357**卡片能力:** 从API version 9开始,该接口支持在ArkTS卡片中使用。 358 359**系统能力:** SystemCapability.ArkUI.ArkUI.Full 360 361| 名称 | 类型 | 只读|可选|说明 | 362| ---------- | ---------------------------------------------------------- | ------|------|---------------- | 363| position | [Position](ts-types.md#position) |否|否| 子组件位置坐标。 | 364| constraint | [ConstraintSizeOptions](ts-types.md#constraintsizeoptions) | 否|否|子组件约束尺寸。 | 365 366 367## 示例 368 369### 示例1(自定义布局代码示例) 370自定义布局代码示例。 371```ts 372// xxx.ets 373@Entry 374@Component 375struct Index { 376 build() { 377 Column() { 378 CustomLayout({ builder: ColumnChildren }) 379 } 380 } 381} 382 383@Builder 384function ColumnChildren() { 385 ForEach([1, 2, 3], (index: number) => { // 目前不支持使用lazyForEach语法。 386 Text('S' + index) 387 .fontSize(30) 388 .width(100) 389 .height(100) 390 .borderWidth(2) 391 .offset({ x: 10, y: 20 }) 392 }) 393} 394 395@Component 396struct CustomLayout { 397 @Builder 398 doNothingBuilder() { 399 }; 400 401 @BuilderParam builder: () => void = this.doNothingBuilder; 402 @State startSize: number = 100; 403 result: SizeResult = { 404 width: 0, 405 height: 0 406 }; 407 408 onPlaceChildren(selfLayoutInfo: GeometryInfo, children: Array<Layoutable>, constraint: ConstraintSizeOptions) { 409 let startPos = 300; 410 children.forEach((child) => { 411 let pos = startPos - child.measureResult.height; 412 child.layout({ x: pos, y: pos }) 413 }) 414 } 415 416 onMeasureSize(selfLayoutInfo: GeometryInfo, children: Array<Measurable>, constraint: ConstraintSizeOptions) { 417 let size = 100; 418 children.forEach((child) => { 419 let result: MeasureResult = child.measure({ minHeight: size, minWidth: size, maxWidth: size, maxHeight: size }) 420 size += result.width / 2 421 ; 422 }) 423 this.result.width = 100; 424 this.result.height = 400; 425 return this.result; 426 } 427 428 build() { 429 this.builder() 430 } 431} 432``` 433 434 435 436### 示例2(判断是否参与布局计算) 437通过组件的位置灵活判断是否参与布局计算。 438```ts 439// xxx.ets 440@Entry 441@Component 442struct Index { 443 build() { 444 Column() { 445 CustomLayout({ builder: ColumnChildren }) 446 } 447 .justifyContent(FlexAlign.Center) 448 .width("100%") 449 .height("100%") 450 } 451} 452 453@Builder 454function ColumnChildren() { 455 ForEach([1, 2, 3], (item: number, index: number) => { // 目前不支持使用lazyForEach语法。 456 Text('S' + item) 457 .fontSize(20) 458 .width(60 + 10 * index) 459 .height(100) 460 .borderWidth(2) 461 .margin({ left:10 }) 462 .padding(10) 463 }) 464} 465 466@Component 467struct CustomLayout { 468 // 只布局一行,如果布局空间不够的子组件不显示的demo。 469 @Builder 470 doNothingBuilder() { 471 }; 472 473 @BuilderParam builder: () => void = this.doNothingBuilder; 474 result: SizeResult = { 475 width: 0, 476 height: 0 477 }; 478 overFlowIndex: number = -1; 479 480 onPlaceChildren(selfLayoutInfo: GeometryInfo, children: Array<Layoutable>, constraint: ConstraintSizeOptions) { 481 let currentX = 0; 482 let infinity = 100000; 483 if (this.overFlowIndex == -1) { 484 this.overFlowIndex = children.length; 485 } 486 for (let index = 0; index < children.length; ++index) { 487 let child = children[index]; 488 if (index >= this.overFlowIndex) { 489 // 如果子组件超出父组件范围,将它布局到较偏的位置,达到不显示的目的。 490 child.layout({x: infinity, y: 0}); 491 continue; 492 } 493 child.layout({ x: currentX, y: 0 }) 494 let margin = child.getMargin(); 495 currentX += child.measureResult.width + margin.start + margin.end; 496 } 497 } 498 499 onMeasureSize(selfLayoutInfo: GeometryInfo, children: Array<Measurable>, constraint: ConstraintSizeOptions) { 500 let width = 0; 501 let height = 0; 502 this.overFlowIndex = -1; 503 // 假定该组件的宽度不能超过200vp,也不能超过最大约束。 504 let maxWidth = Math.min(200, constraint.maxWidth as number); 505 for (let index = 0; index < children.length; ++index) { 506 let child = children[index]; 507 let childResult: MeasureResult = child.measure({ 508 minHeight: constraint.minHeight, 509 minWidth: constraint.minWidth, 510 maxWidth: constraint.maxWidth, 511 maxHeight: constraint.maxHeight 512 }) 513 let margin = child.getMargin(); 514 let newWidth = width + childResult.width + margin.start + margin.end; 515 if (newWidth > maxWidth) { 516 // 记录不该布局的组件的下标。 517 this.overFlowIndex = index; 518 break; 519 } 520 // 累积父组件的宽度和高度。 521 width = newWidth; 522 height = Math.max(height, childResult.height + margin.top + margin.bottom); 523 } 524 this.result.width = width; 525 this.result.height = height; 526 return this.result; 527 } 528 529 build() { 530 this.builder() 531 } 532} 533``` 534 535 536 537### 示例3(获取子组件FrameNode并设置相关属性) 538通过uniqueId获取子组件的[FrameNode](../js-apis-arkui-frameNode.md),并调用FrameNode的API接口修改尺寸、背景颜色。 539```ts 540import { FrameNode, NodeController } from '@kit.ArkUI'; 541@Entry 542@Component 543struct Index { 544 build() { 545 Column() { 546 CustomLayout() 547 } 548 } 549} 550 551class MyNodeController extends NodeController { 552 private rootNode: FrameNode | null = null; 553 makeNode(uiContext: UIContext): FrameNode | null { 554 this.rootNode = new FrameNode(uiContext) 555 return this.rootNode 556 } 557} 558 559@Component 560struct CustomLayout { 561 @Builder 562 childrenBuilder() { 563 ForEach([1, 2, 3], (index: number) => { // 目前不支持使用lazyForEach语法。 564 NodeContainer(new MyNodeController()) 565 }) 566 }; 567 568 @BuilderParam builder: () => void = this.childrenBuilder; 569 result: SizeResult = { 570 width: 0, 571 height: 0 572 }; 573 574 onPlaceChildren(selfLayoutInfo: GeometryInfo, children: Array<Layoutable>, constraint: ConstraintSizeOptions) { 575 let prev = 0; 576 children.forEach((child) => { 577 let pos = prev + 10; 578 prev = pos + child.measureResult.width 579 child.layout({ x: pos, y: 0 }) 580 }) 581 } 582 583 onMeasureSize(selfLayoutInfo: GeometryInfo, children: Array<Measurable>, constraint: ConstraintSizeOptions) { 584 let size = 100; 585 children.forEach((child) => { 586 console.log("child uniqueId: ", child.uniqueId) 587 const uiContext = this.getUIContext() 588 if (uiContext) { 589 let node: FrameNode | null = uiContext.getFrameNodeByUniqueId(child.uniqueId) // 获取NodeContainer组件的FrameNode。 590 if (node) { 591 node.getChild(0)!.commonAttribute.width(100) 592 node.getChild(0)!.commonAttribute.height(100) 593 node.getChild(0)!.commonAttribute.backgroundColor(Color.Pink) // 修改FrameNode的尺寸与背景颜色。 594 } 595 } 596 child.measure({ minHeight: size, minWidth: size, maxWidth: size, maxHeight: size }) 597 }) 598 this.result.width = 320; 599 this.result.height = 100; 600 return this.result; 601 } 602 603 build() { 604 this.builder() 605 } 606} 607``` 608 609 610### 示例4(子组件超过父组件大小约束) 611在自定义布局的自定义组件中,为子组件设置了[LayoutPolicy](./ts-universal-attributes-size.md#layoutpolicy15)对象的fixAtIdealSize属性。 612```ts 613@Entry 614@Component 615struct Index { 616 @Builder 617 ColumnChildrenText() { 618 Text("=====Text=====Text=====Text=====Text=====Text=====Text=====Text=====Text" ) 619 .fontSize(16).fontColor(Color.Black) 620 .borderWidth(2).backgroundColor("#fff8dc") 621 .width(LayoutPolicy.fixAtIdealSize) // 设置子组件宽度不受到父组件限制。 622 .height(LayoutPolicy.fixAtIdealSize) // 设置子组件高度不受到父组件限制。 623 } 624 625 build() { 626 Column() { 627 Column() { 628 CustomLayoutText({ builder: this.ColumnChildrenText }) 629 .backgroundColor("#f0ffff").borderRadius(20).margin(10) 630 } 631 .width(300) 632 .height(150) 633 .margin(10) 634 .backgroundColor(Color.Pink) 635 } 636 .width(350) 637 .height(680) 638 .margin(20) 639 .alignItems(HorizontalAlign.Center) 640 } 641} 642 643@Component 644struct CustomLayoutText { 645 @Builder 646 doSomethingBuilder() { 647 }; 648 649 @BuilderParam 650 builder: () => void = this.doSomethingBuilder; 651 result: SizeResult = { 652 width: 0, 653 height: 0 654 }; 655 // 自定义组件进行自定义布局。 656 onPlaceChildren(selfLayoutInfo: GeometryInfo, children: Array<Layoutable>, constraint: ConstraintSizeOptions) { 657 let posY = 20; 658 children.forEach((child) => { 659 let posX = (selfLayoutInfo.width - child.measureResult.width) / 2; 660 child.layout({ x: posX, y: posY }) 661 posY += child.measureResult.height + 30; 662 }) 663 } 664 665 onMeasureSize(selfLayoutInfo: GeometryInfo, children: Array<Measurable>, constraint: ConstraintSizeOptions) { 666 children.forEach((child) => { 667 let result: MeasureResult = child.measure({ maxWidth: 335, maxHeight: 50 }) // 设置自定义组件子组件大小的限制。 668 }) 669 this.result.width = 200; 670 this.result.height = 130; 671 return this.result; 672 } 673 674 build() { 675 this.builder() 676 } 677} 678``` 679 680 681### 示例5(通过layout修改布局) 682通过layout修改布局。 683<!--deprecated_code_no_check--> 684```ts 685// xxx.ets 686@Entry 687@Component 688struct Index { 689 build() { 690 Column() { 691 CustomLayout() { 692 ForEach([1, 2, 3], (index: number) => { 693 Text('Sub' + index) 694 .fontSize(30) 695 .borderWidth(2) 696 }) 697 } 698 } 699 } 700} 701 702 703@Component 704struct CustomLayout { 705 @Builder 706 doNothingBuilder() { 707 }; 708 709 @BuilderParam builder: () => void = this.doNothingBuilder; 710 711 onLayout(children: Array<LayoutChild>, constraint: ConstraintSizeOptions) { 712 let pos = 0; 713 children.forEach((child) => { 714 child.layout({ position: { x: pos, y: pos }, constraint: constraint }) 715 pos += 70; 716 }) 717 } 718 719 onMeasure(children: Array<LayoutChild>, constraint: ConstraintSizeOptions) { 720 let size = 100; 721 children.forEach((child) => { 722 child.measure({ minHeight: size, minWidth: size, maxWidth: size, maxHeight: size }) 723 size += 50; 724 }) 725 } 726 727 build() { 728 this.builder() 729 } 730} 731``` 732 733