NinePatch 将纹理分为 9 个区域,四角不变、边缘拉伸、中心平铺,实现任意尺寸的 UI 面板/按钮。
九宫格(9-Patch / Nine-Patch)是 UI 开发的核心技术: 将一张小纹理拉伸到任意尺寸,同时保持圆角和边框不变形。 XGE 支持两种初始化方式:Simple(自动三分)和手动指定切割线。
| 函数 | 说明 |
|---|---|
void xgeNinePatchInitSimple(xge_nine_patch pPatch, xge_texture pTexture, xge_rect_t tSrc) | 简单初始化(均分) |
void xgeNinePatchInit(xge_nine_patch pPatch, xge_texture pTexture, xge_rect_t tSrc, float fX1, float fY1, float fX2, float fY2) | 指定切割线 |
void xgeNinePatchSetMode(xge_nine_patch pPatch, int iMode) | 设置拉伸/平铺模式 |
void xgeNinePatchSetColor(xge_nine_patch pPatch, uint32_t iColor) | 设置染色 |
void xgeNinePatchDraw(const xge_nine_patch_t* pPatch, xge_rect_t tDst, uint32_t iFlags) | 绘制到目标矩形 |
gcc -O2 -I. -o ch107.exe ch107_main.c build\xge.lib -lm -lws2_32 -liphlpapi -lgdi32 -luser32 -lshell32 -lopengl32 -lole32 -lwinmm -lavrt
.\ch107.exe
// 加载按钮纹理
xge_texture_t btnTex;
xgeTextureLoad(&btnTex, "ui/button.png");
// 初始化九宫格(切割线:左边 8px,上边 8px,
// 右边距右 8px,下边距下 8px)
xge_nine_patch_t patch;
xgeNinePatchInit(&patch, &btnTex,
(xge_rect_t){ 0, 0, 32, 32 },
8, 8, 24, 24);
// 绘制不同大小的按钮(圆角不变形)
xgeNinePatchDraw(&patch,
(xge_rect_t){ 100, 100, 120, 40 }, 0);
xgeNinePatchDraw(&patch,
(xge_rect_t){ 100, 160, 200, 60 }, 0);
// 染色(如禁用态灰色)
xgeNinePatchSetColor(&patch, 0x808080FF);
xgeNinePatchDraw(&patch,
(xge_rect_t){ 100, 240, 120, 40 }, 0);将以下代码保存为 ch107_main.c,编译后运行即可看到九宫格拉伸效果:
#include "xge.h"
#include <string.h>
static xge_texture_t g_tex;
static xge_nine_patch_t g_patch;
static xge_font g_font = NULL;
static int onFrame(void* pUser) {
(void)pUser;
xgeClear(0x081114FF);
// 绘制不同大小的按钮(圆角不变形)
xgeNinePatchSetColor(&g_patch, 0xFFFFFFFF);
xgeNinePatchDraw(&g_patch,
(xge_rect_t){ 100, 100, 120, 40 }, 0);
xgeNinePatchDraw(&g_patch,
(xge_rect_t){ 100, 160, 200, 60 }, 0);
xgeNinePatchDraw(&g_patch,
(xge_rect_t){ 100, 240, 300, 80 }, 0);
// 染色(禁用态灰色)
xgeNinePatchSetColor(&g_patch, 0x808080FF);
xgeNinePatchDraw(&g_patch,
(xge_rect_t){ 100, 340, 120, 40 }, 0);
xgeTextDraw(g_font, "Nine-Patch: corners stay fixed",
100.0f, 50.0f, 0xFFFFFFFF)
return XGE_OK;
}
int main(void) {
xge_desc_t d = {0};
d.iWidth = 800;
d.iHeight = 600;
d.sTitle = "ch107 - Nine-Patch UI";
d.iFlags = XGE_INIT_VSYNC;
xgeInit(&d);
xgeFontLoad(&g_font, "Roboto.ttf", 18.0f);
// 程序生成 32x32 圆角按钮纹理
uint8_t px[32 * 32 * 4];
memset(px, 0, sizeof(px));
for (int y = 0; y < 32; y++)
for (int x = 0; x < 32; x++) {
int i = (y * 32 + x) * 4;
px[i] = 80; px[i+1] = 140;
px[i+2] = 220; px[i+3] = 255;
}
xgeTextureCreateRGBA(&g_tex, 32, 32, px);
// 初始化九宫格(切割线 8px)
xgeNinePatchInit(&g_patch, &g_tex,
(xge_rect_t){ 0, 0, 32, 32 },
8, 8, 24, 24);
xgeRun(onFrame, NULL);
xgeTextureFree(&g_tex);
xgeFontFree(g_font);
xgeUnit();
return 0;
}