使用布局组件
======

从API version 12开始，ArkUI在NDK中提供了常用布局组件[Flex](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-flex)、[Row](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-row)、[Column](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-column)、[Stack](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-stack)对应的节点类型和属性设置接口。Flex用于弹性布局，Row和Column用于线性布局，Stack用于层叠布局，对应节点类型和属性设置枚举可参考[ArkUI\_NodeType](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-node-h#arkui_nodetype)。

本文以弹性组件Flex为例，提供NDK下布局组件接入和属性设置的开发指导。本示例仅展示核心功能代码，完整示例请参考[NDKFlexSample](https://gitcode.com/HarmonyOS_Samples/guide-snippets/tree/master/ArkUISample/NDKFlexSample)；实现前需要先接入ArkTS页面，具体接入方式可参考[接入ArkTS页面](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/ndk-access-the-arkts-page)。

#### 封装容器组件

通过调用[createNode](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-arkui-nativemodule-arkui-nativenodeapi-1#createnode)接口，并传入ArkUI\_NodeType中的ARKUI\_NODE\_FLEX，创建Flex节点。如下示例将该节点封装为ArkUIFlexNode，并通过[setAttribute](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-arkui-nativemodule-arkui-nativenodeapi-1#setattribute)接口，使用NODE\_FLEX\_OPTION设置主轴方向、换行和对齐方式。ArkUI\_NumberValue中的五个参数分别用于控制不同的弹性布局行为，具体可参考[FlexOptions对象说明](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-flex#flexoptions对象说明)。

class ArkUIFlexNode : public ArkUINode {
public:
    ArkUIFlexNode()
        : ArkUINode((NativeModuleInstance::GetInstance()->GetNativeNodeAPI())->createNode(ARKUI\_NODE\_FLEX)) {}

    ~ArkUIFlexNode() override = default;

    void SetFlexOption(ArkUI\_FlexDirection direction, ArkUI\_FlexWrap wrap, ArkUI\_FlexAlignment justifyContent,
        ArkUI\_ItemAlignment alignItems, ArkUI\_FlexAlignment alignContent)
    {
        ArkUI\_NumberValue value\[\] = {
            {.i32 = direction},
            {.i32 = wrap},
            {.i32 = justifyContent},
            {.i32 = alignItems},
            {.i32 = alignContent}
        };
        ArkUI\_AttributeItem item = {value, 5};
        nativeModule\_->setAttribute(handle\_, NODE\_FLEX\_OPTION, &item);
    }
};

节点创建完成后，通过预实现的通用属性和上文实现的SetFlexOption，构造了一个预设样式的Flex组件。下面代码展示了如何设置容器按行排列子组件、子组件超出宽度后自动换行、每一行默认从起始位置开始布局。

inline std::shared\_ptr<ArkUIFlexNode> CreateFlexContainer()
{
    auto flex = std::make\_shared<ArkUIFlexNode>();
    flex->SetPercentWidth(FULL\_SIZE);
    flex->SetHeight(SECTION\_HEIGHT\_LARGE);
    flex->SetBackgroundColor(SECTION\_BACKGROUND\_COLOR);
    flex->SetFlexOption(ARKUI\_FLEX\_DIRECTION\_ROW, ARKUI\_FLEX\_WRAP\_WRAP, ARKUI\_FLEX\_ALIGNMENT\_START,
        ARKUI\_ITEM\_ALIGNMENT\_CENTER, ARKUI\_FLEX\_ALIGNMENT\_START);
    return flex;
}

#### 添加子组件

如下示例为弹性容器添加了一组子组件。为展示换行和交叉轴对齐效果，为第三个子组件设置单独的高度和[alignSelf](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-universal-attributes-flex-layout#alignself)。alignSelf是在弹性容器内生效的组件通用属性，将该属性设置封装到自定义接口SetAlignSelf中，通过NODE\_ALIGN\_SELF设置在指定组件上，可以控制单个子组件在父容器交叉轴的对齐格式，且优先级高于容器的[alignItems](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-flex#flexoptions对象说明)属性。

inline void SetAlignSelf(const std::shared\_ptr<ArkUIBaseNode> &node, ArkUI\_ItemAlignment align)
{
    ArkUI\_NumberValue value\[\] = {{.i32 = align}};
    ArkUI\_AttributeItem item = {value, 1};
    NativeModuleInstance::GetInstance()->GetNativeNodeAPI()->setAttribute(node->GetHandle(), NODE\_ALIGN\_SELF, &item);
}

inline std::shared\_ptr<ArkUITextNode> CreateFlexExampleItem(int32\_t index, uint32\_t bgColor)
{
    auto item = CreateFixedItem("Flex " + std::to\_string(index + 1), bgColor);
    if (index == ALIGN\_SELF\_ITEM\_INDEX) { item->SetHeight(ALIGN\_SELF\_ITEM\_HEIGHT); }
    if (index == ALIGN\_SELF\_ITEM\_INDEX) { SetAlignSelf(item, ARKUI\_ITEM\_ALIGNMENT\_END); }
    return item;
}

在此基础上，创建6个子组件，并添加到同一个Flex组件。

inline std::array<uint32\_t, FLEX\_ITEM\_COUNT> CreateFlexColorSet()
{
    return {FLEX\_ITEM\_BLUE, FLEX\_ITEM\_GREEN, FLEX\_ITEM\_ORANGE, FLEX\_ITEM\_PINK, FLEX\_ITEM\_PURPLE, FLEX\_ITEM\_TEAL};
}

inline std::shared\_ptr<ArkUIFlexNode> CreateFlexWrapExample()
{
    auto flex = CreateFlexContainer();
    const auto flexColors = CreateFlexColorSet();
    for (int32\_t index = 0; index < static\_cast<int32\_t>(flexColors.size()); ++index) { // 循环遍历数组，添加一组子节点
        flex->AddChild(CreateFlexExampleItem(index, flexColors\[index\]));
    }
    return flex;
}

此时，CreateFlexContainer()已将Flex组件的换行行为设置为ARKUI\_FLEX\_WRAP\_WRAP，因此当子组件总宽度超过容器宽度时，布局会自动换行；而第三个子组件调用SetAlignSelf()后，会按照自身的交叉轴对齐规则摆放，而不是使用容器设置的ARKUI\_ITEM\_ALIGNMENT\_CENTER。

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/b/v3/xySJx8bqQtiG1j23dCm5_A/zh-cn_image_0000002625107775.jpg?HW-CC-KV=V1&HW-CC-Date=20260612T073315Z&HW-CC-Expire=86400&HW-CC-Sign=3004432C05316BC24C1A3A026519041AF8860A752CA6104A20A1B94FF9D0EDC9)

如果要将布局方向改为纵向，则可将direction改为ARKUI\_FLEX\_DIRECTION\_COLUMN。此时代码结构保持不变，主轴和交叉轴上的摆放逻辑也保持一致。

#### 使用flexBasis和flexGrow分配剩余空间

Flex不仅能够控制子组件排列方向，还能够控制主轴上的剩余空间分配。通过[flexBasis](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-universal-attributes-flex-layout#flexbasis)、[flexGrow](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-universal-attributes-flex-layout#flexgrow)和[flexShrink](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-universal-attributes-flex-layout#flexshrink)三个属性，可以控制子组件的在弹性容器下伸缩行为。

inline void SetFlexGrow(const std::shared\_ptr<ArkUIBaseNode> &node, float grow)
{
    ArkUI\_NumberValue value\[\] = {{.f32 = grow}};
    ArkUI\_AttributeItem item = {value, 1};
    NativeModuleInstance::GetInstance()->GetNativeNodeAPI()->setAttribute(node->GetHandle(), NODE\_FLEX\_GROW, &item);
}

inline void SetFlexShrink(const std::shared\_ptr<ArkUIBaseNode> &node, float shrink)
{
    ArkUI\_NumberValue value\[\] = {{.f32 = shrink}};
    ArkUI\_AttributeItem item = {value, 1};
    NativeModuleInstance::GetInstance()->GetNativeNodeAPI()->setAttribute(
        node->GetHandle(), NODE\_FLEX\_SHRINK, &item);
}

inline void SetFlexBasis(const std::shared\_ptr<ArkUIBaseNode> &node, float basis)
{
    ArkUI\_NumberValue value\[\] = {{.f32 = basis}};
    ArkUI\_AttributeItem item = {value, 1};
    NativeModuleInstance::GetInstance()->GetNativeNodeAPI()->setAttribute(node->GetHandle(), NODE\_FLEX\_BASIS, &item);
}

inline std::shared\_ptr<ArkUITextNode> CreateGrowItem(
    const std::string &text, uint32\_t bgColor, float grow, float shrink = 0.0F)
{
    auto item = CreateFlexibleItem(text, bgColor);
    SetFlexBasis(item, FLEX\_BASIS);
    SetFlexGrow(item, grow);
    SetFlexShrink(item, shrink);
    return item;
}

inline std::shared\_ptr<ArkUIRowNode> CreateFlexGrowExample()
{
    auto growRow = CreateRowContainer();
    growRow->AddChild(CreateGrowItem("1", COLUMN\_ITEM\_BLUE, DEFAULT\_FLEX\_GROW));
    growRow->AddChild(CreateGrowItem("2", COLUMN\_ITEM\_GREEN, EMPHASIZED\_FLEX\_GROW, EMPHASIZED\_FLEX\_SHRINK));
    growRow->AddChild(CreateGrowItem("1", COLUMN\_ITEM\_PINK, DEFAULT\_FLEX\_GROW));
    return growRow;
}

先用SetFlexBasis()给子组件设置主轴上的基准尺寸，再用SetFlexGrow()指定剩余空间的分配比例，最后用SetFlexShrink()定义空间不足时的压缩比例。

示例中三个子组件的flexGrow值分别为1、2、1，因此在容器存在剩余空间时，中间子组件会占据更多宽度。

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/3d/v3/RkMaCqjMSTyW54Ry1c8dEA/zh-cn_image_0000002594668258.jpg?HW-CC-KV=V1&HW-CC-Date=20260612T073315Z&HW-CC-Expire=86400&HW-CC-Sign=E4F85BFB0B6449A834C83D924F757B48B36F66A11579376544DAA4BEDA7B4AD3)

#### 使用layoutWeight按比例分配空间

当父容器主轴尺寸已经确定时，可以通过[layoutWeight](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-universal-attributes-size#layoutweight)按权重分配剩余空间。该属性在Row、Column和Flex中生效。子组件设置的layoutWeight值大于0后，会按照权重占比分配主轴剩余空间，不再参与flexGrow和flexShrink的分配。

inline void SetLayoutWeight(const std::shared\_ptr<ArkUIBaseNode> &node, uint32\_t weight)
{
    ArkUI\_NumberValue value\[\] = {{.u32 = weight}};
    ArkUI\_AttributeItem item = {value, 1};
    NativeModuleInstance::GetInstance()->GetNativeNodeAPI()->setAttribute(
        node->GetHandle(), NODE\_LAYOUT\_WEIGHT, &item);
}

inline std::shared\_ptr<ArkUITextNode> CreateWeightedItem(const std::string &text, uint32\_t bgColor, uint32\_t weight)
{
    auto item = CreateFlexibleItem(text, bgColor);
    SetLayoutWeight(item, weight);
    return item;
}

inline std::shared\_ptr<ArkUIRowNode> CreateLayoutWeightExample()
{
    auto weightRow = CreateRowContainer();
    weightRow->AddChild(CreateWeightedItem("Weight 1", COLUMN\_ITEM\_BLUE, DEFAULT\_LAYOUT\_WEIGHT));
    weightRow->AddChild(CreateWeightedItem("Weight 2", COLUMN\_ITEM\_GREEN, EMPHASIZED\_LAYOUT\_WEIGHT));
    weightRow->AddChild(CreateWeightedItem("Weight 1", COLUMN\_ITEM\_PINK, DEFAULT\_LAYOUT\_WEIGHT));
    return weightRow;
}

示例中三个子组件的layoutWeight值分别为1、2、1，因此中间子组件会分得更多主轴空间。

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/42/v3/2iPlgaNIQwyU4Yt3JZnAVg/zh-cn_image_0000002594828186.jpg?HW-CC-KV=V1&HW-CC-Date=20260612T073315Z&HW-CC-Expire=86400&HW-CC-Sign=547BFF4AFCC23642FA73C2F7C02132C19D9A5F1EE488B50908E55381B1034A3D)

#### 使用displayPriority控制显示优先级

在单行布局场景下，可以通过[displayPriority](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-universal-attributes-layout-constraints#displaypriority)控制子组件的显示优先级。该属性在Row、Column和单行Flex中生效。父容器空间不足时，优先级低的子组件会先被隐藏。

inline void SetDisplayPriority(const std::shared\_ptr<ArkUIBaseNode> &node, uint32\_t priority)
{
    ArkUI\_NumberValue value\[\] = {{.u32 = priority}};
    ArkUI\_AttributeItem item = {value, 1};
    NativeModuleInstance::GetInstance()->GetNativeNodeAPI()->setAttribute(
        node->GetHandle(), NODE\_DISPLAY\_PRIORITY, &item);
}

inline std::shared\_ptr<ArkUITextNode> CreatePriorityItem(
    const std::string &text, uint32\_t bgColor, uint32\_t priority)
{
    auto item = CreateFixedItem(text, bgColor);
    SetDisplayPriority(item, priority);
    return item;
}

inline std::shared\_ptr<ArkUIRowNode> CreateDisplayPriorityExample()
{
    auto priorityRow = CreateRowContainer();
    priorityRow->SetWidth(DISPLAY\_PRIORITY\_ROW\_WIDTH);
    priorityRow->SetJustifyContent(ARKUI\_FLEX\_ALIGNMENT\_START);
    priorityRow->AddChild(CreatePriorityItem("High", COLUMN\_ITEM\_BLUE, HIGH\_DISPLAY\_PRIORITY));
    priorityRow->AddChild(CreatePriorityItem("Mid", COLUMN\_ITEM\_GREEN, MEDIUM\_DISPLAY\_PRIORITY));
    priorityRow->AddChild(CreatePriorityItem("Low", COLUMN\_ITEM\_PINK, LOW\_DISPLAY\_PRIORITY));
    return priorityRow;
}

示例先设置了较窄的Row容器宽度，再分别设置3、2、1三个优先级。当空间不足时，优先级最低的第三个子组件会先隐藏。

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/b0/v3/LYPBiwMBRmuro48rHnsZ7A/zh-cn_image_0000002625187633.jpg?HW-CC-KV=V1&HW-CC-Date=20260612T073315Z&HW-CC-Expire=86400&HW-CC-Sign=93BF821BDCFE6285A62E4EF7C08B5B23BE728949507D207657283BDBCD99FC72)