ScrollView 提供可滚动视口,支持惯性滚动、弹性回弹、内容拖拽、滚动条策略配置。
ScrollView 由三层结构组成:
• Frame:外框(含滚动条)
• Viewport:可视窗口,裁剪超出内容
• Content:实际内容容器,可大于视口
滚动偏移 (OffsetX, OffsetY) 控制 Content 在 Viewport 中的位置。支持鼠标滚轮、拖拽内容、滚动条三种交互方式。
| 函数 | 说明 |
|---|---|
int xuiScrollViewCreate(xui_context pCtx, xui_widget* ppW, const xui_scroll_view_desc_t* pDesc) | 创建滚动视图 |
xui_widget xuiScrollViewGetContentWidget(xui_widget pW) | 获取内容容器 |
int xuiScrollViewSetContentSize(xui_widget pW, float fW, float fH) | 设置内容尺寸 |
int xuiScrollViewSetOffset(xui_widget pW, float fX, float fY) | 设置滚动偏移 |
int xuiScrollViewScrollBy(xui_widget pW, float fDX, float fDY) | 增量滚动 |
int xuiScrollViewEnsureChildVisible(xui_widget pW, xui_widget pChild) | 确保子控件可见 |
int xuiScrollViewSetScrollbarPolicy(xui_widget pW, int iPX, int iPY) | 滚动条策略 |
int xuiScrollViewSetScrollbarMode(xui_widget pW, int iMode) | 滚动条模式 |
int xuiScrollViewSetWheelStep(xui_widget pW, float fStep) | 滚轮步长 |
int xuiScrollViewSetContentDragEnabled(xui_widget pW, int bEnabled) | 内容拖拽 |
gcc -O2 -I. -o ch144.exe ch144_main.c src\xui_*.c build\xge.lib -lm -lws2_32 -liphlpapi -lgdi32 -luser32 -lshell32 -lopengl32 -lole32 -lwinmm -lavrt
.\ch144.exe
xui_scroll_view_desc_t desc = { 0 };
xui_widget pScroll;
xuiScrollViewCreate(pCtx, &pScroll, &desc);
xuiWidgetSetRect(pScroll, (xui_rect_t){0, 0, 300.0f, 400.0f});
// 设置内容高度(100 个 40px 高的条目)
xuiScrollViewSetContentSize(pScroll, 300.0f, 4000.0f);
xuiScrollViewSetWheelStep(pScroll, 40.0f);
xuiScrollViewSetContentDragEnabled(pScroll, 1);
// 滚动条策略:Y 轴自动显示,X 轴隐藏
xuiScrollViewSetScrollbarPolicy(pScroll, 0, 1);
// 向内容区添加子控件
xui_widget pContent = xuiScrollViewGetContentWidget(pScroll);
xuiWidgetSetLayout(pContent, XUI_LAYOUT_COLUMN);
xuiWidgetAddChild(pParent, pScroll);将以下代码保存为 ch144_main.c,编译后运行即可看到滚动视图效果:
#include "xge.h"
#include "xui.h"
#include <stdio.h>
static xui_context g_pCtx;
static int onFrame(void* pUser) {
(void)pUser;
xgeClear(0x081114FF);
/* 注入鼠标输入以支持滚轮/拖拽 */
float mx, my;
xgeMouseGet(&mx, &my);
xuiInputPointerMove(g_pCtx, mx, my);
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 = "ch144 - ScrollView";
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);
/* 根容器 */
xui_widget pRoot;
xuiWidgetCreate(g_pCtx, &pRoot);
xuiWidgetSetLayoutType(pRoot, XUI_LAYOUT_COLUMN);
xuiWidgetSetRect(pRoot, (xui_rect_t){0, 0, 800, 600});
xuiWidgetSetPadding(pRoot, 40, 40, 40, 40);
xuiSetRootWidget(g_pCtx, pRoot);
/* 创建滚动视图 */
xui_scroll_view_desc_t svd = { 0 };
xui_widget pScroll;
xuiScrollViewCreate(g_pCtx, &pScroll, &svd);
xuiWidgetSetRect(pScroll, (xui_rect_t){0, 0, 400, 500});
xuiScrollViewSetContentSize(pScroll, 400, 2000);
xuiScrollViewSetWheelStep(pScroll, 40.0f);
xuiScrollViewSetContentDragEnabled(pScroll, 1);
xuiScrollViewSetScrollbarPolicy(pScroll, 0, 1);
xuiWidgetAddChild(pRoot, pScroll);
/* 向内容区添加 50 个标签 */
xui_widget pContent = xuiScrollViewGetContentWidget(pScroll);
xuiWidgetSetLayout(pContent, XUI_LAYOUT_COLUMN);
static char buf[50][32];
for (int i = 0; i < 50; i++) {
sprintf(buf[i], "Item #%d", i + 1);
xui_label_desc_t lb = { 0 };
lb.sText = buf[i];
xui_widget pLb;
xuiLabelCreate(g_pCtx, &pLb, &lb);
xuiWidgetSetRect(pLb, (xui_rect_t){0, 0, 380, 36});
xuiWidgetAddChild(pContent, pLb);
}
xgeRun(onFrame, NULL);
xuiDestroy(g_pCtx);
xgeUnit();
return 0;
}