• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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&lt;Measurable&gt;, 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&lt;[Measurable](#measurable10)&gt;                   | 是|计算子组件大小后的子组件布局信息。<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&lt;Layoutable&gt;, 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&lt;[Layoutable](#layoutable10)&gt;                   |是 |计算子组件大小后的子组件布局信息。         |
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&lt;number&gt;](./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&lt;number&gt;](./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&lt;number&gt;](./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&lt;number&gt;](./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&lt;number&gt;](./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&lt;number&gt;](./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&lt;LayoutChild&gt;, 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&lt;[LayoutChild](#layoutchilddeprecated)&gt;                | 是  | 子组件布局信息。         |
294| constraint | [ConstraintSizeOptions](ts-types.md#constraintsizeoptions) | 是  |父组件constraint信息。 |
295
296## onMeasure<sup>(deprecated)</sup>
297
298onMeasure?(children: Array&lt;LayoutChild&gt;, 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&lt;[LayoutChild](#layoutchilddeprecated)&gt;                  | 是  |子组件布局信息。         |
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![custom_layout10.png](figures/custom_layout10.png)
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![custom_layout_demo2.png](figures/custom_layout_demo2.png)
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![custom_layout_demo3.jpg](figures/custom_layout_demo3.jpg)
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![custom_layout_demo4.jpg](figures/custom_layout_demo4.jpg)
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![zh-cn_image_0000001511900496](figures/zh-cn_image_0000001511900496.png)