Chapter 161 · XUI 弹出层与反馈

Toast 轻提示

Toast 浮动轻提示通知,支持类型图标、标题+消息、放置位置、队列管理、点击回调。

161

概念

Toast 是非阻塞浮动通知:
• 浮层:不占据布局空间,覆盖在内容之上
• 队列:多条 Toast 依次排列显示
• Placement:TopLeft / TopRight / BottomLeft / BottomRight / TopCenter / BottomCenter
• Direction:新 Toast 出现方向(向上堆叠/向下堆叠)
• 点击回调:用户点击 Toast 触发操作

API 速查

函数说明
int xuiToastCreate(xui_context pCtx, xui_toast* ppToast, const xui_toast_desc_t* pDesc)创建 Toast 管理器
void xuiToastDestroy(xui_toast pToast)销毁
int xuiToastShow(xui_toast pT, int iType, const char* sTitle, const char* sMsg, float fDur, onClick, void* pUser)显示一条 Toast
int xuiToastClose(xui_toast pT, int iToastId)关闭指定 Toast
int xuiToastSetPlacement(xui_toast pT, int iPlacement)放置位置
int xuiToastSetDirection(xui_toast pT, int iDirection)堆叠方向
int xuiToastSetMetrics(xui_toast pT, float fWidth, float fGap, float fMargin)尺寸间距

编译本章示例

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

示例:操作反馈通知

xui_toast_desc_t desc = { 0 };

xui_toast pToast;
xuiToastCreate(pCtx, &pToast, &desc);
xuiToastSetPlacement(pToast, 1);  // TopRight

// 成功通知
xuiToastShow(pToast, 1, "成功", "文件已保存",
    3.0f, NULL, NULL);

// 错误通知(可点击查看详情)
xuiToastShow(pToast, 3, "错误", "网络连接失败",
    5.0f, OnToastClick, pAppData);

static void OnToastClick(int iToastId, void* pUser) {
    ShowNetworkDiagnostic();
    xuiToastClose(pToast, iToastId);
}

完整代码

将以下代码保存为 ch161_main.c,编译后运行即可看到 Toast 轻提示效果:

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

static xui_context g_pCtx;
static xui_toast   g_pToast;
static int         g_iIdx = 0;

static void OnBtnClick(xui_widget pW, int iValue, void* pUser) {
    (void)pW; (void)iValue; (void)pUser;
    static const char* sTitles[] = { "信息", "成功", "警告", "错误" };
    static const char* sMsgs[]   = { "已复制到剪贴板", "文件保存成功",
                                     "内存使用率 90%", "连接超时" };
    xuiToastShow(g_pToast, g_iIdx, sTitles[g_iIdx], sMsgs[g_iIdx],
        3.0f, NULL, NULL);
    g_iIdx = (g_iIdx + 1) % 4;
}

static int onFrame(void* pUser) {
    (void)pUser;
    xgeClear(0x081114FF);
    xui_vec2_t pos; xgeMouseGet(&pos.x, &pos.y);
    xuiInputPointerMove(g_pCtx, pos.x, pos.y);
    if (xgeMouseDown(XGE_MOUSE_LEFT)) xuiInputPointerDown(g_pCtx, pos.x, pos.y, 0);
    else xuiInputPointerUp(g_pCtx, pos.x, pos.y, 0);
    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 = "ch161 - Toast";
    d.iFlags = XGE_INIT_VSYNC;
    xgeInit(&d);
    xuiCreate(&g_pCtx);
    /* XGE 官方代理由 xuiProxyXge() 提供 */
    xui_proxy_t tXgeProxy = xuiProxyXge();
xuiSetProxy(g_pCtx, &tXgeProxy);
    xuiSetViewportSize(g_pCtx, 800, 600);

    xui_widget pRoot;
    xuiPanelCreate(g_pCtx, &pRoot, NULL);
    xuiWidgetSetRect(pRoot, (xui_rect_t){0, 0, 800, 600});

    /* Toast 管理器 */
    xui_toast_desc_t tDesc = {0};
    xuiToastCreate(g_pCtx, &g_pToast, &tDesc);
    xuiToastSetPlacement(g_pToast, 1); /* TopRight */

    /* 触发按钮 */
    xui_widget pBtn;
    xuiButtonCreate(g_pCtx, &pBtn, NULL);
    xuiWidgetSetRect(pBtn, (xui_rect_t){0, 0, 160, 36});
    xuiWidgetSetRect(pBtn, (xui_rect_t){320, 300, 160, 36});
    xuiButtonSetText(pBtn, "弹出 Toast");
    xuiButtonSetClick(pBtn, OnBtnClick, NULL);
    xuiWidgetAddChild(pRoot, pBtn);

    xgeRun(onFrame, NULL);
    xuiToastDestroy(g_pToast);
    xuiDestroy(g_pCtx);
    xgeUnit();
    return 0;
}

代码讲解

  • xuiToastCreate:创建 Toast 管理器,独立于控件树。
  • xuiToastSetPlacement(1):设置 Toast 出现在右上角。
  • xuiToastShow:参数为类型、标题、消息、持续时间、点击回调。
  • 循环类型:每次点击切换 Info→Success→Warning→Error。
  • 非阻塞:Toast 不影响用户继续操作,到时自动消失。

要点与陷阱

  • ToastId:Show 返回唯一 ID,用于 Close 指定条目。
  • Duration:单位秒,到时自动消失并触发关闭动画。
  • 队列上限:超出可见数量时旧 Toast 被挤出。
  • 非模态:Toast 不阻塞用户操作,适合轻量反馈。

进阶练习

  1. 下载进度 Toast:显示文件名 + 进度条,完成后变为 Success。
  2. 多位置切换:设置面板中选择 Toast 出现位置。
Toast 轻提示效果
图:Toast 轻提示渲染效果