Chapter 127 · XUI 框架架构

布局系统:Row / Column / Flow

Row 水平排列、Column 垂直排列、Flow 自动换行,支持 grow/shrink 弹性分配。

127

概念

弹性布局是 UI 开发最常用的模式:
• ROW (2):子控件从左到右水平排列
• COLUMN (3):子控件从上到下垂直排列
• FLOW (4):水平排列,空间不足时自动换行
每个子控件可设置 grow(伸展因子)和 shrink(收缩因子), 实现类似 CSS Flexbox 的弹性分配。

API 速查

宏/函数说明
XUI_LAYOUT_ROW水平排列 (2)
XUI_LAYOUT_COLUMN垂直排列 (3)
XUI_LAYOUT_FLOW流式换行 (4)
int xuiWidgetSetFlex(xui_widget pWidget, float fGrow, float fShrink)设置伸展因子
int xuiWidgetGetFlex(xui_widget pWidget, float* pGrow, float* pShrink)设置收缩因子
int xuiWidgetSetPadding(xui_widget pWidget, xui_thickness_t tPadding)设置内边距

编译本章示例

gcc -O2 -I. -o ch127.exe ch127_main.c src\xui_*.c build\xge.lib -lm -lws2_32 -liphlpapi -lgdi32 -luser32 -lshell32 -lopengl32 -lole32 -lwinmm -lavrt
.\ch127.exe

示例:工具栏 + 侧边栏

// 水平工具栏(Row)
xuiWidgetSetLayoutType(pToolbar, XUI_LAYOUT_ROW);
xuiWidgetSetGap(pToolbar, 4);
xuiWidgetSetPadding(pToolbar,
    (xui_thickness_t){ 8, 4, 8, 4 });

// 按钮固定宽度,搜索框弹性伸展
xuiWidgetSetFlex(pSearchInput, 1.0f, 1.0f);
// 按钮 grow=0(默认),保持固有宽度

// 垂直侧边栏(Column)
xuiWidgetSetLayoutType(pSidebar, XUI_LAYOUT_COLUMN);
xuiWidgetSetGap(pSidebar, 8);

// 列表区域弹性填满剩余空间
xuiWidgetSetFlex(pListView, 1.0f, 1.0f);

// 流式标签(Flow)
xuiWidgetSetLayoutType(pTagContainer, XUI_LAYOUT_FLOW);
xuiWidgetSetGap(pTagContainer, 6);
// 标签自动换行排列

完整代码

将以下代码保存为 ch127_main.c,编译后运行即可看到 Row/Column/Flow 弹性布局:

#include "xge.h"
#include "xui.h"

static xui_context g_pCtx;

static int onFrame(void* pUser) {
    (void)pUser;
    xgeClear(0x081114FF);
    xuiUpdate(g_pCtx, xgeGetDelta());
    xuiLayout(g_pCtx);
    xuiRender(g_pCtx, NULL, NULL, 0);
    return XGE_OK;
}

int main(void) {
    xge_desc_t d = {0};
    d.iWidth  = 800;
    d.iHeight = 600;
    d.sTitle  = "ch127 - Row/Column/Flow";
    d.iFlags  = XGE_INIT_VSYNC;
    xgeInit(&d);

    xuiCreate(&g_pCtx);
    extern const xui_proxy_t tXgeProxy;
    xui_proxy_t tXgeProxy = xuiProxyXge();
xuiSetProxy(g_pCtx, &tXgeProxy);
    xuiSetViewportSize(g_pCtx, 800, 600);

    // 根控件:Column 布局
    xui_widget pRoot;
    xuiWidgetCreate(g_pCtx, &pRoot);
    xuiWidgetSetLayoutType(pRoot, XUI_LAYOUT_COLUMN);
    xuiWidgetSetGap(pRoot, 8);
    xuiWidgetSetPadding(pRoot,
        (xui_thickness_t){ 10, 10, 10, 10 });

    // 工具栏:Row 布局
    xui_widget pToolbar;
    xuiWidgetCreate(g_pCtx, &pToolbar);
    xuiWidgetSetLayoutType(pToolbar, XUI_LAYOUT_ROW);
    xuiWidgetSetGap(pToolbar, 4);

    // 按钮固定宽 + 搜索框弹性伸展
    xui_widget pBtn1, pBtn2, pSearch;
    xuiWidgetCreate(g_pCtx, &pBtn1);
    xuiWidgetCreate(g_pCtx, &pBtn2);
    xuiWidgetCreate(g_pCtx, &pSearch);
    xuiWidgetSetFlex(pSearch, 1.0f, 1.0f);
    xuiWidgetAddChild(pToolbar, pBtn1);
    xuiWidgetAddChild(pToolbar, pBtn2);
    xuiWidgetAddChild(pToolbar, pSearch);
    xuiWidgetAddChild(pRoot, pToolbar);

    // 标签容器:Flow 布局(自动换行)
    xui_widget pTags;
    xuiWidgetCreate(g_pCtx, &pTags);
    xuiWidgetSetLayoutType(pTags, XUI_LAYOUT_FLOW);
    xuiWidgetSetGap(pTags, 6);
    xuiWidgetSetFlex(pTags, 1.0f, 1.0f);
    xuiWidgetAddChild(pRoot, pTags);

    xgeRun(onFrame, NULL);

    xuiDestroy(g_pCtx);
    xgeUnit();
    return 0;
}

代码讲解

  • XUI_LAYOUT_ROW:子控件水平排列,适合工具栏。
  • XUI_LAYOUT_COLUMN:子控件垂直排列,适合侧边栏/表单。
  • XUI_LAYOUT_FLOW:水平排列并自动换行,适合标签云。
  • xuiWidgetSetFlex:设置伸展/收缩因子,剩余空间按 grow 比例分配。
  • 间距与内边距:通过内联样式等样式属性控制。

要点与陷阱

  • Grow:剩余空间按 grow 比例分配(0=不伸展)。
  • Shrink:空间不足时按 shrink 比例收缩(0=不收缩)。
  • Gap:子控件之间的固定间距。
  • Flow 换行:宽度不够时自动折到下一行。

进阶练习

  1. 实现响应式布局:窗口缩小时 Column 切换为 Flow。
  2. 表单布局:标签固定宽 + 输入框 grow=1。
布局系统:Row / Column / Flow效果
图:布局系统:Row / Column / Flow渲染效果