设置通用布局属性
========

从API version 12开始，ArkUI在NDK中提供了一组通用布局属性，可以控制组件的尺寸、位置、边框等布局行为。

本文选取了尺寸设置（[width](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-universal-attributes-size#width)、[height](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-universal-attributes-size#height)、[size](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-universal-attributes-size#size)、[aspectRatio](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-universal-attributes-layout-constraints#aspectratio)、[padding](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-universal-attributes-size#padding)、[margin](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-universal-attributes-size#margin)、[layoutWeight](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-universal-attributes-size#layoutweight)）、位置设置（[position](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-universal-attributes-location#position)、[offset](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-universal-attributes-location#offset)）、边框设置（[borderWidth](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-universal-attributes-border#borderwidth)、[borderColor](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-universal-attributes-border#bordercolor)、[borderStyle](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-universal-attributes-border#borderstyle)、[borderRadius](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-universal-attributes-border#borderradius)）三个典型场景，提供NDK下通用布局属性接入的开发指导，对应属性设置和参数类型枚举可参考[ArkUI\_NodeType](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-node-h#arkui_nodetype)。

本示例仅展示核心功能代码，完整示例请参考[NDKLayoutSample](https://gitcode.com/HarmonyOS_Samples/guide-snippets/tree/master/ArkUISample/NDKLayoutSample)；实现前需要先接入ArkTS页面，具体接入方式可参考[接入ArkTS页面](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/ndk-access-the-arkts-page)。

#### 设置组件尺寸

NDK通用布局属性的推荐使用方式是：先在节点类中封装属性设置方法，再在具体组件上调用。以下示例封装了一组固定尺寸与宽高比属性。

void SetWidth(float width)
{
    ArkUI\_NumberValue value\[\] = {{.f32 = width}};
    ArkUI\_AttributeItem item = {value, 1};
    nativeModule\_->setAttribute(handle\_, NODE\_WIDTH, &item);
}

void SetPercentWidth(float percent)
{
    ArkUI\_NumberValue value\[\] = {{.f32 = percent}};
    ArkUI\_AttributeItem item = {value, 1};
    nativeModule\_->setAttribute(handle\_, NODE\_WIDTH\_PERCENT, &item);
}

void SetHeight(float height)
{
    ArkUI\_NumberValue value\[\] = {{.f32 = height}};
    ArkUI\_AttributeItem item = {value, 1};
    nativeModule\_->setAttribute(handle\_, NODE\_HEIGHT, &item);
}

void SetSize(float width, float height)
{
    ArkUI\_NumberValue value\[\] = {{.f32 = width}, {.f32 = height}};
    ArkUI\_AttributeItem item = {value, 2};
    nativeModule\_->setAttribute(handle\_, NODE\_SIZE, &item);
}

void SetAspectRatio(float ratio)
{
    ArkUI\_NumberValue value\[\] = {{.f32 = ratio}};
    ArkUI\_AttributeItem item = {value, 1};
    nativeModule\_->setAttribute(handle\_, NODE\_ASPECT\_RATIO, &item);
}

在组件上组合使用这些方法，可以观察到固定尺寸、百分比尺寸和宽高比生效。

inline std::shared\_ptr<ArkUITextNode> CreateFixedSizeItem()
{
    auto fixedItem = CreateDemoItem("NODE\_SIZE\\n112 x 68vp", SIZE\_ITEM\_BLUE);
    fixedItem->SetSize(FIXED\_ITEM\_WIDTH, FIXED\_ITEM\_HEIGHT);
    fixedItem->SetMargin(0.0F, SAMPLE\_GAP, 0.0F, 0.0F);
    return fixedItem;
}

inline std::shared\_ptr<ArkUITextNode> CreateAspectRatioItem()
{
    auto ratioItem = CreateDemoItem("height=64\\naspectRatio=2.0", SIZE\_ITEM\_GREEN);
    ratioItem->SetHeight(RATIO\_ITEM\_HEIGHT);
    ratioItem->SetAspectRatio(RATIO\_VALUE);
    ratioItem->SetMargin(0.0F, SAMPLE\_GAP, 0.0F, 0.0F);
    return ratioItem;
}

inline std::shared\_ptr<ArkUITextNode> CreatePercentWidthItem()
{
    auto percentItem = CreateDemoItem("width=30%", SIZE\_ITEM\_ORANGE);
    percentItem->SetPercentWidth(PERCENT\_WIDTH\_VALUE);
    percentItem->SetHeight(RATIO\_ITEM\_HEIGHT);
    return percentItem;
}

SetSize()同时写入宽和高，适合固定尺寸组件；SetPercentWidth()通过入参常量PERCENT\_WIDTH\_VALUE配置组件宽度为父容器宽度的30%；SetAspectRatio()通过配置固定宽高比，从显式设置的组件高度自动推导对应的宽度。

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/cc/v3/lThAKHK2SpebvBsrX9pooQ/zh-cn_image_0000002625107777.jpg?HW-CC-KV=V1&HW-CC-Date=20260612T073315Z&HW-CC-Expire=86400&HW-CC-Sign=FCE3D2F2D0E405843594AE68DF815727BDD48922BAFB9CBCA9B75CDCC63EF63C)

通常，还需要通过padding和margin控制内外边距、调节组件尺寸，以实现良好的间距效果。

void SetPadding(float top, float right, float bottom, float left)
{
    ArkUI\_NumberValue value\[\] = {{.f32 = top}, {.f32 = right}, {.f32 = bottom}, {.f32 = left}};
    ArkUI\_AttributeItem item = {value, 4};
    nativeModule\_->setAttribute(handle\_, NODE\_PADDING, &item);
}

void SetPercentPadding(float top, float right, float bottom, float left)
{
    ArkUI\_NumberValue value\[\] = {{.f32 = top}, {.f32 = right}, {.f32 = bottom}, {.f32 = left}};
    ArkUI\_AttributeItem item = {value, 4};
    nativeModule\_->setAttribute(handle\_, NODE\_PADDING\_PERCENT, &item);
}

void SetMargin(float top, float right, float bottom, float left)
{
    ArkUI\_NumberValue value\[\] = {{.f32 = top}, {.f32 = right}, {.f32 = bottom}, {.f32 = left}};
    ArkUI\_AttributeItem item = {value, 4};
    nativeModule\_->setAttribute(handle\_, NODE\_MARGIN, &item);
}

void SetPercentMargin(float percent)
{
    ArkUI\_NumberValue value\[\] = {{.f32 = percent}};
    ArkUI\_AttributeItem item = {value, 1};
    nativeModule\_->setAttribute(handle\_, NODE\_MARGIN\_PERCENT, &item);
}

inline std::shared\_ptr<ArkUITextNode> CreatePercentWidthPaddingItem()
{
    auto inner = CreateDemoItem("内容区", PADDING\_ITEM\_BLUE);
    inner->SetPercentWidth(FULL\_SIZE);
    return inner;
}

inline std::shared\_ptr<ArkUIColumnNode> CreatePaddingHost()
{
    auto paddingHost = std::make\_shared<ArkUIColumnNode>();
    paddingHost->SetPercentWidth(FULL\_SIZE);
    paddingHost->SetHeight(SPACING\_PADDING\_HOST\_HEIGHT);
    paddingHost->SetBackgroundColor(SURFACE\_BACKGROUND\_COLOR);
    paddingHost->SetPadding(PADDING\_TOP, PADDING\_RIGHT, PADDING\_TOP, PADDING\_RIGHT);
    paddingHost->SetMargin(0.0F, 0.0F, CARD\_MARGIN\_BOTTOM, 0.0F);
    paddingHost->AddChild(CreatePercentWidthPaddingItem());
    return paddingHost;
}

inline std::shared\_ptr<ArkUITextNode> CreateMarginItem(const std::string &text, uint32\_t color, bool addSpacing = false)
{
    auto item = CreateDemoItem(text, color);
    item->SetWidth(SMALL\_ITEM\_WIDTH);
    if (addSpacing) { item->SetMargin(0.0F, SAMPLE\_GAP, 0.0F, 0.0F); }
    return item;
}

内边距padding用于控制组件内容区与边缘之间的留白，外边距margin用于控制组件与父容器边缘的留白间距。如果需要按父容器比例设置间距，则可使用[ArkUI\_NodeType](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-node-h#arkui_nodetype)中NODE\_PADDING\_PERCENT和NODE\_MARGIN\_PERCENT对应的方法。

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/58/v3/fvrcYwyeT2uhDpI37wllQw/zh-cn_image_0000002594668260.jpg?HW-CC-KV=V1&HW-CC-Date=20260612T073315Z&HW-CC-Expire=86400&HW-CC-Sign=2064BDDA575C87818C9CD408FCC06EA2701D67D9A1572172E5D89ABD20B56246)

#### 使用位置属性

当尺寸和间距已经确定后，如果需要进一步调整组件摆放位置，可以使用[position](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-universal-attributes-location#position)和[offset](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-universal-attributes-location#offset)。两者都会改变组件的显示位置，但含义不同。position表示相对父容器进行定位，offset表示在原有布局结果上发生偏移。

void SetPosition(float x, float y)
{
    ArkUI\_NumberValue value\[\] = {{.f32 = x}, {.f32 = y}};
    ArkUI\_AttributeItem item = {value, 2};
    nativeModule\_->setAttribute(handle\_, NODE\_POSITION, &item);
}

void SetOffset(float x, float y)
{
    ArkUI\_NumberValue value\[\] = {{.f32 = x}, {.f32 = y}};
    ArkUI\_AttributeItem item = {value, 2};
    nativeModule\_->setAttribute(handle\_, NODE\_OFFSET, &item);
}

分别将这两个属性施加在不同组件上对比。

inline std::shared\_ptr<ArkUITextNode> CreatePositionedItem()
{
    auto positioned = CreateDemoItem("position(20, 18)", POSITION\_ITEM\_ORANGE);
    positioned->SetWidth(LARGE\_ITEM\_WIDTH);
    positioned->SetPosition(POSITION\_X, POSITION\_Y);
    return positioned;
}

inline std::shared\_ptr<ArkUITextNode> CreateOffsetItem()
{
    auto offset = CreateDemoItem("offset(110, 80)", POSITION\_ITEM\_BLUE);
    offset->SetWidth(LARGE\_ITEM\_WIDTH);
    offset->SetMargin(OFFSET\_MARGIN\_TOP, 0.0F, 0.0F, 0.0F);
    offset->SetOffset(OFFSET\_X, POSITION\_Y);
    return offset;
}

可以看到两种效果：position直接给出目标位置，offset则保留原有占位关系，再向目标方向偏移。

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/13/v3/7kN9gI45SLqWWCZ4HYWs8w/zh-cn_image_0000002594828188.jpg?HW-CC-KV=V1&HW-CC-Date=20260612T073315Z&HW-CC-Expire=86400&HW-CC-Sign=701E76F0B533E66250A966DBCC94357DD988EE0EC4B7985BAC8579EA00B45D08)

#### 使用边框属性

边框属性在NDK中的使用方式与上文一致，同样是先封装方法，再在具体组件上组合调用。方法封装如下。

void SetBorderWidth(float width)
{
    ArkUI\_NumberValue value\[\] = {{.f32 = width}};
    ArkUI\_AttributeItem item = {value, 1};
    nativeModule\_->setAttribute(handle\_, NODE\_BORDER\_WIDTH, &item);
}

void SetBorderColor(uint32\_t color)
{
    ArkUI\_NumberValue value\[\] = {{.u32 = color}};
    ArkUI\_AttributeItem item = {value, 1};
    nativeModule\_->setAttribute(handle\_, NODE\_BORDER\_COLOR, &item);
}

void SetBorderStyle(ArkUI\_BorderStyle style)
{
    ArkUI\_NumberValue value\[\] = {{.i32 = style}};
    ArkUI\_AttributeItem item = {value, 1};
    nativeModule\_->setAttribute(handle\_, NODE\_BORDER\_STYLE, &item);
}

void SetBorderRadius(float radius)
{
    ArkUI\_NumberValue value\[\] = {{.f32 = radius}};
    ArkUI\_AttributeItem item = {value, 1};
    nativeModule\_->setAttribute(handle\_, NODE\_BORDER\_RADIUS, &item);
}

当组件已经具备尺寸和间距后，可以继续叠加这些边框属性，构建轮廓和视觉分隔的效果。

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/76/v3/81kX9jUSQOiuNFz4dm742Q/zh-cn_image_0000002625187635.jpg?HW-CC-KV=V1&HW-CC-Date=20260612T073315Z&HW-CC-Expire=86400&HW-CC-Sign=A91C79BED7AC490F26A173744C07B04CD9488BEE6E8287F9AE9B86FEF3EC82FF)