目录

Custom Component Layout

The custom layout of a custom component is used to lay out its child components through data calculation.

The initial APIs of this module are supported since API version 9. Newly added APIs will be marked with a superscript to indicate their earliest API version.

A custom component is considered to have a custom layout when either of the onMeasureSize or onPlaceChildren methods is implemented. For complete layout control, implement both methods simultaneously. For details about the specifications, see the API descriptions for these methods.

Since API version 20, when child components within a custom layout have their LayoutPolicy object's fixAtIdealSize property set to true, these components will ignore any layout constraints from their parent component. Instead, they will adhere to the size ranges explicitly defined by the developer in the custom layout implementation.

Lazy loading (including Repeat and LazyForEach) is not supported in custom layouts.

onMeasureSize10+

onMeasureSize?(selfLayoutInfo: GeometryInfo, children: Array<Measurable>, constraint: ConstraintSizeOptions): SizeResult

Invoked when the custom component needs to determine its size. Through this callback the component receives its layout information and size constraints from the ArkUI framework. State variables should not be changed in this callback.

Atomic service API: This API can be used in atomic services since API version 11.

System capability: SystemCapability.ArkUI.ArkUI.Full

Parameters

Name Type Mandatory Description
selfLayoutInfo GeometryInfo Yes

Information about the component's computed layout properties after measurement.

NOTE

During the first layout, the component will use its own set attributes as the basis for layout.

children Array<Measurable> Yes

Array containing layout information for all child components after measurement.

NOTE

When a child component does not have its layout information set, it retains the previous layout settings or, if no previous layout settings are available, stays at the default size of 0.

constraint ConstraintSizeOptions Yes Layout constraints applied to the component.

Return value

Type Description
SizeResult Component size information.

onPlaceChildren10+

onPlaceChildren?(selfLayoutInfo: GeometryInfo, children: Array<Layoutable>, constraint: ConstraintSizeOptions): void

Invoked when the custom component needs to determine the positions of its child components. Through this callback the component receives its child component size constraints from the ArkUI framework. State variables should not be changed in this callback.

Atomic service API: This API can be used in atomic services since API version 11.

System capability: SystemCapability.ArkUI.ArkUI.Full

Parameters

Name Type Mandatory Description
selfLayoutInfo GeometryInfo Yes Information about the component's computed layout properties after measurement.
children Array<Layoutable> Yes Array containing layout information for all child components after measurement.
constraint ConstraintSizeOptions Yes Layout constraints applied to the component.

Example

See the example for customizing a layout.

GeometryInfo10+

Provides layout geometry information of the parent component (a custom component). Inherits from SizeResult.

Atomic service API: This API can be used in atomic services since API version 11.

System capability: SystemCapability.ArkUI.ArkUI.Full

Name Type Read-Only Optional Description
borderWidth EdgeWidth No No

Width of the parent component's border.

Unit: vp.

margin Margin No No

Margin values of the parent component.

Unit: vp.

padding Padding No No

Padding values of the parent component.

Unit: vp.

Layoutable10+

Provides the child component layout information.

System capability: SystemCapability.ArkUI.ArkUI.Full

[h2]Name

Name Type Read-Only Optional Description
measureResult MeasureResult No No

Measurement result of the child component.

Atomic service API: This API can be used in atomic services since API version 11.

Unit: vp

uniqueId18+ number No Yes

Unique ID that the system assigns to the child component.

Value range: [0, +∞)

Atomic service API: This API can be used in atomic services since API version 18.

[h2]layout10+

layout(position: Position): void

Applies the specified position constraints to the child component.

Atomic service API: This API can be used in atomic services since API version 11.

System capability: SystemCapability.ArkUI.ArkUI.Full

Parameters

Name Type Mandatory Description
position Position Yes Absolute position.

[h2]getMargin12+

getMargin(): DirectionalEdgesT<number>

Obtains the margin values of the child component.

Atomic service API: This API can be used in atomic services since API version 12.

System capability: SystemCapability.ArkUI.ArkUI.Full

Return value

Type Description
DirectionalEdgesT<number> Margin values of the child component.

[h2]getPadding12+

getPadding(): DirectionalEdgesT<number>

Obtains the padding values of the child component.

Atomic service API: This API can be used in atomic services since API version 12.

System capability: SystemCapability.ArkUI.ArkUI.Full

Return value

Type Description
DirectionalEdgesT<number> Padding values of the child component.

[h2]getBorderWidth12+

getBorderWidth(): DirectionalEdgesT<number>

Obtains the border widths of the child component.

Atomic service API: This API can be used in atomic services since API version 12.

System capability: SystemCapability.ArkUI.ArkUI.Full

Return value

Type Description
DirectionalEdgesT<number> Border widths of the child component.

Measurable10+

Provides the child component position information.

Atomic service API: This API can be used in atomic services since API version 11.

System capability: SystemCapability.ArkUI.ArkUI.Full

[h2]Name

Atomic service API: This API can be used in atomic services since API version 18.

System capability: SystemCapability.ArkUI.ArkUI.Full

Name Type Read-Only Optional Description
uniqueId18+ number No Yes Unique ID that the system assigns to the child component.

[h2]measure

measure(constraint: ConstraintSizeOptions) : MeasureResult

Imposes size constraints on the child component.

Atomic service API: This API can be used in atomic services since API version 11.

System capability: SystemCapability.ArkUI.ArkUI.Full

Parameters

Name Type Mandatory Description
constraint ConstraintSizeOptions Yes Size constraint.

Return value

Type Description
MeasureResult Provides the measurement result of the component.

[h2]getMargin12+

getMargin(): DirectionalEdgesT<number>

Obtains the margin values of the child component.

Atomic service API: This API can be used in atomic services since API version 12.

System capability: SystemCapability.ArkUI.ArkUI.Full

Return value

Type Description
DirectionalEdgesT<number> Margin values of the child component.

[h2]getPadding12+

getPadding(): DirectionalEdgesT<number>

Obtains the padding values of the child component.

Atomic service API: This API can be used in atomic services since API version 12.

System capability: SystemCapability.ArkUI.ArkUI.Full

Return value

Type Description
DirectionalEdgesT<number> Padding values of the child component.

[h2]getBorderWidth12+

getBorderWidth(): DirectionalEdgesT<number>

Obtains the border widths of the child component.

Atomic service API: This API can be used in atomic services since API version 12.

System capability: SystemCapability.ArkUI.ArkUI.Full

Return value

Type Description
DirectionalEdgesT<number> Border widths of the child component.

MeasureResult10+

Provides the measurement result of the component. This API inherits from SizeResult.

Atomic service API: This API can be used in atomic services since API version 11.

System capability: SystemCapability.ArkUI.ArkUI.Full

SizeResult10+

Provides the component size information.

  • The custom layout does not support the LazyForEach syntax.
  • When a custom layout is created in builder mode, only this.builder() is allowed in the build() method of a custom component, as shown in the recommended usage in the example below.
  • The size parameters of the parent component (custom component), except aspectRatio, are at a lower priority than those specified by onMeasureSize.
  • The position parameters of the child component, except offset, position, and markAnchor, are at a lower priority than those specified by onPlaceChildren, and do not take effect.
  • When using the custom layout method, you must call onMeasureSize and onPlaceChildren at the same time for the layout to display properly.

Atomic service API: This API can be used in atomic services since API version 11.

System capability: SystemCapability.ArkUI.ArkUI.Full

Name Type Read-Only Optional Description
width number No No

Width obtained from the measurement result.

Unit: vp.

height number No No

Height obtained from the measurement result.

Unit: vp.

onLayout(deprecated)

onLayout?(children: Array<LayoutChild>, constraint: ConstraintSizeOptions): void

Invoked when the custom component lays out its child components. Through this callback the component receives its child component layout information and size constraint from the ArkUI framework. State variables should not be changed in this callback.

This API is supported since API version 9 and deprecated since API version 10. You are advised to use onPlaceChildren instead.

Widget capability: This API can be used in ArkTS widgets since API version 9.

System capability: SystemCapability.ArkUI.ArkUI.Full

Parameters

Name Type Mandatory Description
children Array<LayoutChild> Yes Child component layout information.
constraint ConstraintSizeOptions Yes Size constraint of the parent component.

onMeasure(deprecated)

onMeasure?(children: Array<LayoutChild>, constraint: ConstraintSizeOptions): void

Invoked when the custom component needs to determine its size. Through this callback the component receives its child component layout information and its own size constraints from the ArkUI framework. State variables should not be changed in this callback.

This API is supported since API version 9 and deprecated since API version 10. You are advised to use onMeasureSize instead.

Widget capability: This API can be used in ArkTS widgets since API version 9.

System capability: SystemCapability.ArkUI.ArkUI.Full

Parameters

Name Type Mandatory Description
children Array<LayoutChild> Yes Child component layout information.
constraint ConstraintSizeOptions Yes Size constraint of the parent component.

LayoutChild(deprecated)

Provides the child component layout information.

This API is supported since API version 9 and deprecated since API version 10. You are advised to use Measurable or Layoutable instead.

[h2]Name

Widget capability: This API can be used in ArkTS widgets since API version 9.

System capability: SystemCapability.ArkUI.ArkUI.Full

Name Type Read-Only Optional Description
name string No No Name of the child component.
id string No No ID of the child component.
constraint ConstraintSizeOptions No No Constraint size of the child component.
borderInfo LayoutBorderInfo No No Provides the border information of the child component.
position Position No No Position coordinates of the child component.

[h2]measure(deprecated)

measure(childConstraint: ConstraintSizeOptions)

Applies specified size constraints to child components.

This API is supported since API version 9 and deprecated since API version 10. You are advised to use Measurable or Layoutable instead.

Widget capability: This API can be used in ArkTS widgets since API version 9.

System capability: SystemCapability.ArkUI.ArkUI.Full

Parameters

Name Type Mandatory Description
childConstraint ConstraintSizeOptions Yes Size constraints to apply to child components.

[h2]layout(deprecated)

layout(childLayoutInfo: LayoutInfo)

Applies the specified layout constraints to the child component.

This API is supported since API version 9 and deprecated since API version 10. You are advised to use Measurable or Layoutable instead.

Widget capability: This API can be used in ArkTS widgets since API version 9.

System capability: SystemCapability.ArkUI.ArkUI.Full

Parameters

Name Type Mandatory Description
childLayoutInfo LayoutInfo Yes Layout information of the child component.

LayoutBorderInfo(deprecated)

Provides the border information of the child component.

This API is supported since API version 9 and deprecated since API version 10. You are advised to use getBorderWidth, getMargin, and getPadding instead.

Widget capability: This API can be used in ArkTS widgets since API version 9.

System capability: SystemCapability.ArkUI.ArkUI.Full

Name Type Read-Only Optional Description
borderWidth EdgeWidths No No Edge widths in different directions of the component.
margin Margin No No Margin values in different directions of the component.
padding Padding No No Padding values in different directions of the component.

LayoutInfo(deprecated)

Provides the child component layout information.

This API is supported since API version 9 and deprecated since API version 10.

Widget capability: This API can be used in ArkTS widgets since API version 9.

System capability: SystemCapability.ArkUI.ArkUI.Full

Name Type Read-Only Optional Description
position Position No No Position coordinates of the child component.
constraint ConstraintSizeOptions No No Constraint size of the child component.

Example

[h2]Example 1: Implementing a Custom Layout

This example demonstrates how to implement a custom layout.

// xxx.ets
@Entry
@Component
struct Index {
  build() {
    Column() {
      CustomLayout({ builder: ColumnChildren })
    }
  }
}

@Builder
function ColumnChildren() {
  ForEach([1, 2, 3], (index: number) => { // LazyForEach is not supported.
    Text('S' + index)
      .fontSize(30)
      .width(100)
      .height(100)
      .borderWidth(2)
      .offset({ x: 10, y: 20 })
  })
}

@Component
struct CustomLayout {
  @Builder
  doNothingBuilder() {
  };

  @BuilderParam builder: () => void = this.doNothingBuilder;
  @State startSize: number = 100;
  result: SizeResult = {
    width: 0,
    height: 0
  };

  onPlaceChildren(selfLayoutInfo: GeometryInfo, children: Array<Layoutable>, constraint: ConstraintSizeOptions) {
    let startPos = 300;
    children.forEach((child) => {
      let pos = startPos - child.measureResult.height;
      child.layout({ x: pos, y: pos })
    })
  }

  onMeasureSize(selfLayoutInfo: GeometryInfo, children: Array<Measurable>, constraint: ConstraintSizeOptions) {
    let size = 100;
    children.forEach((child) => {
      let result: MeasureResult = child.measure({
        minHeight: size,
        minWidth: size,
        maxWidth: size,
        maxHeight: size
      })
      size += result.width / 2;
    })
    this.result.width = 100;
    this.result.height = 400;
    return this.result;
  }

  build() {
    this.builder()
  }
}

[h2]Example 2: Determining Whether to Participate in Layout Calculation

This example shows how to determine whether a component participates in layout calculation based on its position.

// xxx.ets
@Entry
@Component
struct Index {
  build() {
    Column() {
      CustomLayout({ builder: ColumnChildren })
    }
    .justifyContent(FlexAlign.Center)
    .width('100%')
    .height('100%')
  }
}

@Builder
function ColumnChildren() {
  ForEach([1, 2, 3], (item: number, index: number) => { // LazyForEach is not supported.
    Text('S' + item)
      .fontSize(20)
      .width(60 + 10 * index)
      .height(100)
      .borderWidth(2)
      .margin({ left:10 })
      .padding(10)
  })
}

@Component
struct CustomLayout {
  // Lay out only one row, and hide child components that are too large for the available space.
  @Builder
  doNothingBuilder() {
  };

  @BuilderParam builder: () => void = this.doNothingBuilder;
  result: SizeResult = {
    width: 0,
    height: 0
  };
  overFlowIndex: number = -1;

  onPlaceChildren(selfLayoutInfo: GeometryInfo, children: Array<Layoutable>, constraint: ConstraintSizeOptions) {
    let currentX = 0;
    let infinity = 100000;
    if (this.overFlowIndex == -1) {
      this.overFlowIndex = children.length;
    }
    for (let index = 0; index < children.length; ++index) {
      let child = children[index];
      if (index >= this.overFlowIndex) {
        // Hide any child component that extends beyond the area of its parent component by placing it in a distant position.
        child.layout({x: infinity, y: 0});
        continue;
      }
      child.layout({ x: currentX, y: 0 })
      let margin = child.getMargin();
      currentX += child.measureResult.width + margin.start + margin.end;
    }
  }

  onMeasureSize(selfLayoutInfo: GeometryInfo, children: Array<Measurable>, constraint: ConstraintSizeOptions) {
    let width = 0;
    let height = 0;
    this.overFlowIndex = -1;
    // Restrict the maximum width of the parent component to the smaller value between 200 vp and the maximum width from layout constraints.
    let maxWidth = Math.min(200, constraint.maxWidth as number);
    for (let index = 0; index < children.length; ++index) {
      let child = children[index];
      let childResult: MeasureResult = child.measure({
          minHeight: constraint.minHeight,
          minWidth: constraint.minWidth,
          maxWidth: constraint.maxWidth,
          maxHeight: constraint.maxHeight
      })
      let margin = child.getMargin();
      let newWidth = width + childResult.width + margin.start + margin.end;
      if (newWidth > maxWidth) {
        // Record the index of the component that should not be laid out.
        this.overFlowIndex = index;
        break;
      }
      // Update the parent component's cumulative width and height.
      width = newWidth;
      height = Math.max(height, childResult.height + margin.top + margin.bottom);
    }
    this.result.width = width;
    this.result.height = height;
    return this.result;
  }

  build() {
    this.builder()
  }
}

[h2]Example 4: Allowing the Child Component to Ignore Parent Component Size Constraints

This example demonstrates how to use the fixAtIdealSize property of the LayoutPolicy object to allow the child component to ignore parent component size constraints.

@Entry
@Component
struct Index {
  @Builder
  ColumnChildrenText() {
    Text('=====Text=====Text=====Text=====Text=====Text=====Text=====Text=====Text' )
      .fontSize(16).fontColor(Color.Black)
      .borderWidth(2).backgroundColor('#fff8dc')
      .width(LayoutPolicy.fixAtIdealSize) // Set the child component's width to be unrestricted by the parent component.
      .height(LayoutPolicy.fixAtIdealSize)  // Set the child component's height to be unrestricted by the parent component.
  }

  build() {
    Column() {
      Column() {
        CustomLayoutText({ builder: this.ColumnChildrenText })
          .backgroundColor('#f0ffff').borderRadius(20).margin(10)
      }
      .width(300)
      .height(150)
      .margin(10)
      .backgroundColor(Color.Pink)
    }
    .width(350)
    .height(680)
    .margin(20)
    .alignItems(HorizontalAlign.Center)
  }
}

@Component
struct CustomLayoutText {
  @Builder
  doSomethingBuilder() {
  };

  @BuilderParam
  builder: () => void = this.doSomethingBuilder;
  result: SizeResult = {
    width: 0,
    height: 0
  };
  // The custom component implements custom layout.
  onPlaceChildren(selfLayoutInfo: GeometryInfo, children: Array<Layoutable>, constraint: ConstraintSizeOptions) {
    let posY = 20;
    children.forEach((child) => {
      let posX = (selfLayoutInfo.width - child.measureResult.width) / 2;
      child.layout({ x: posX, y: posY })
      posY += child.measureResult.height + 30;
    })
  }

  onMeasureSize(selfLayoutInfo: GeometryInfo, children: Array<Measurable>, constraint: ConstraintSizeOptions) {
    children.forEach((child) => {
      let result: MeasureResult = child.measure({ maxWidth: 335, maxHeight: 50 }) // Set constraints on the size of the child component of the custom component.
    })
    this.result.width = 200;
    this.result.height = 130;
    return this.result;
  }

  build() {
    this.builder()
  }
}