STTStyle.h 提供三类能力:
这些 API 基本直接调用 LVGL,不做范围、空指针或线程检查。
通过控件取得样式:
widget->getStyle()->p_bg
->setColor(0xffffff)
->setOpa(255);
不要长期缓存返回的 STTStyle*:
// 不安全
STTStyle* aStyle = widgetA->getStyle();
widgetB->getStyle();
aStyle->p_bg->setColor(0xff0000); // 实际可能改到 widgetB
当前 STTStyleHelper::attach 全进程只复用一个 global_stt_style_helper。每次 attach/getStyle 都会把同一包装器及其子属性对象重新指向最新 object。因此:
安全写法:
widgetA->getStyle()->p_bg->setColor(0xff0000);
widgetB->getStyle()->p_bg->setColor(0x00ff00);
selector 是“部件 | 状态”:
部件常用值:
| 值 | 部件 |
|---|---|
| 0x000000 | Main |
| 0x010000 | Scrollbar |
| 0x020000 | Indicator |
| 0x030000 | Knob |
| 0x040000 | Selected |
| 0x050000 | Items |
| 0x060000 | Ticks |
| 0x070000 | Cursor |
| 0x080000 | Custom first |
| 0x0F0000 | Any part |
状态常用值:
| 值 | 状态 |
|---|---|
| 0x0000 | Default |
| 0x0001 | Checked |
| 0x0002 | Focused |
| 0x0004 | Focus key |
| 0x0008 | Edited |
| 0x0010 | Hovered |
| 0x0020 | Pressed |
| 0x0040 | Scrolled |
| 0x0080 | Disabled |
int selector = stt::constant::Part::Indic |
stt::constant::WidgetState::CHECKED;
widget->getStyle()->p_bg->setColor(0x18a765, selector);
STTStyle 构造/attach 的 selector 成员当前没有自动合并到每个方法的默认 selector。需要非 Main/Default 时,始终给具体 set/get 方法显式传 selector。
| 类型 | 用途 |
|---|---|
| LvCoord | 坐标,当前 USE_LARGE_COORD=1 时为 int32_t |
| LvPoint | x/y 点,提供默认和 (x,y) 构造 |
| LvArea | x1/y1/x2/y2 绝对区域 |
| LvColor | BGRA 分量或 full 颜色 |
| LvImgHeader / LvImgDsc | 图片头和像素数据描述 |
| LvGradientStop / LvGradDsc | 两段渐变描述 |
| LvDrawRectDsc | 矩形背景、图片、边框、外框、阴影 |
| LvDrawArcDsc | 圆弧绘制参数 |
| LvDrawLabelDsc | 文字绘制参数 |
| LvDrawImgDsc | 图片旋转、缩放、重着色 |
| LvDrawLineDsc | 直线、虚线和端帽 |
| LvChartSeries / LvChartCursor | 图表系列/光标内部映射 |
| LvMeterScale / LvMeterIndicator | 仪表标尺/指示器内部映射 |
| LvStyleValue / LvStyleConstProp / LvStyle | LVGL 样式内部映射 |
这些结构体直接映射特定 LVGL 版本 ABI。升级 LVGL 后字段顺序、位域和大小可能变化,不应用于持久化或网络传输,也不要跨不同编译版本共享二进制内存。
LvDrawRectDsc rect;
rect.bg_opa = 255;
rect.bg_color.full = 0x1687d9;
LvDrawArcDsc arc;
arc.width = 4;
arc.color.full = 0xff0000;
LvDrawLineDsc line;
line.width = 2;
line.color.full = 0x333333;
LvDrawRectDsc、LvDrawArcDsc、LvDrawLabelDsc、LvDrawLineDsc 有构造函数。
严重实现问题:无参 LvDrawLabelDsc() 调用 lv_memset_00(this, sizeof(LvDrawRectDsc)),使用了错误且通常更大的结构体大小,可能覆盖相邻内存。当前版本不要使用无参构造:
// 避免:LvDrawLabelDsc dsc;
void* font = widget->getFont(18);
LvDrawLabelDsc dsc(font); // 使用显式字体构造
更稳妥的是使用原生 lv_draw_label_dsc_t 与 lv_draw_label_dsc_init,再在需要 STT 接口时确认布局兼容。
主属性:
| 方法 | 说明 |
|---|---|
| setRadius / getRadius | 圆角 |
| setWidth | 样式宽度 |
| setClipCorner / getClipCorner | 是否裁剪圆角外子内容 |
| setOpa / getOpa | 总体透明度 |
| setBlendMode / getBlendMode | 混合模式 |
| setLayout / getLayout | Flex/Grid 布局 ID |
| setBaseDir / getBaseDir | LTR、RTL、Auto |
| setColorFilterOpa / getColorFilterOpa | 状态颜色过滤透明度 |
| add / remove | 添加或删除 LvStyle |
| attach | 重定向包装器到另一个 lv_obj |
widget->getStyle()
->setRadius(8)
->setOpa(255)
->setClipCorner(true)
->setBaseDir(0);
add/remove 使用的 LvStyle* 必须在附着期间持续有效。remove(nullptr, selector) 按 selector 移除匹配样式,默认是 Any part/Any state,影响范围很大。
公开子属性:
p_bg, p_border, p_transform, p_img, p_outline,
p_pad, p_shadow, p_text, p_translate, p_line,
p_arc, p_anim, p_location, p_size, p_scrollbar
它们由 STTStyle 构造并析构,调用方不得 delete。
auto* size = widget->getStyle()->p_size;
size->setWidth(200)
->setMinWidth(100)
->setMaxWidth(400)
->setHeight(80)
->setMinHeight(40)
->setMaxHeight(160);
size->setSize(64);
读取:getWidth、getMinWidth、getMaxWidth、getHeight、getMinHeight、getMaxHeight。
这些是“样式尺寸”,与 STTWidget::setWidth/setHeight 的直接对象尺寸语义不同。布局中最终结果受 min/max、百分比、content 和父布局共同影响。
auto* location = widget->getStyle()->p_location;
location->setX(10)->setY(20)->setAlign(ALIGN::CENTER);
int x = location->getX();
int y = location->getY();
int align = location->getAlign();
方法:setX、setY、setAlign、getX、getY、getAlign。它们操作 style x/y/align,不更新 STTWidget 的 mSetted 缓存。
样式动画参数:
auto* animStyle = widget->getStyle()->p_anim;
animStyle->setTime(500)->setSpeed(120);
int time = animStyle->getTime();
int speed = animStyle->getSpeed();
通用动画:
static void applyX(void* target, int32_t value) {
((STTWidget*)target)->setX(value);
}
static void onDeleted(void* anim) {
STTWidget* target =
(STTWidget*)STTStyleAnim::getSTTWidget(anim);
}
void* handle = widget->getStyle()->p_anim->doAnim(
widget,
0, 200,
500,
applyX,
onDeleted,
0,
0,
0,
3
);
pathcb:0 linear、1 ease in、2 ease out、3 ease in/out、4 overshoot、5 bounce、6 step。
repeat<0 无限。finishcb 实际被注册为 LVGL deleted callback,经 reinterpret_cast 后接收到的是 lv_anim_t*,不是 STTWidget*;通过 getSTTWidget 取 var。
bool stopped = widget->getStyle()->p_anim->stopAnim(widget, handle);
handle 是 LVGL 管理的内部指针,动画删除后失效。传 nullptr 时按 var/空 exec_cb 删除第一个匹配动画,不一定是业务期望的那一个。
方法:
setWidth, setRounded, setColor, setOpa, setImgSrc
getWidth, getRounded, getColor, getOpa, getImgSrc
widget->getStyle()->p_arc
->setWidth(12, Part::Indic)
->setRounded(true, Part::Indic)
->setColor(0x1687d9, Part::Indic)
->setOpa(255, Part::Indic);
图片源为 const void*,必须符合 LVGL 图片源规则并保持有效。
方法:
setWidth, setDashWidth, setDashGap, setRounded, setColor, setOpa
getWidth, getDashWidth, getDashGap, getRounded, getColor, getOpa
widget->getStyle()->p_line
->setWidth(3)
->setDashWidth(8)
->setDashGap(4)
->setRounded(true)
->setColor(0x333333)
->setOpa(255);
斜线虚线在 LVGL 中可能受限制。
方法:
setWidth, setOfsX, setOfsY, setSpread, setColor, setOpa
getWidth, getOfsX, getOfsY, getSpread, getColor, getOpa
widget->getStyle()->p_shadow
->setWidth(12)
->setOfsX(0)
->setOfsY(4)
->setSpread(1)
->setColor(0x000000)
->setOpa(80);
大阴影显著扩大重绘区域。
方法:
setWidth, setColor, setOpa, setPad
getWidth, getColor, getOpa, getPad
widget->getStyle()->p_outline
->setWidth(2, WidgetState::FOCUSED)
->setColor(0x1687d9, WidgetState::FOCUSED)
->setOpa(255, WidgetState::FOCUSED)
->setPad(2, WidgetState::FOCUSED);
outline 不占布局尺寸,可能绘制到控件外。
方法:
setOpa, setRecolor, setRecolorOpa
getOpa, getRecolor, getRecolorOpa
widget->getStyle()->p_img
->setOpa(255)
->setRecolor(0xff0000)
->setRecolorOpa(100);
recolorOpa=0 保持原色,255 完全重着色。
方法:
setColor, setOpa, setFont, setLetterSpace, setLineSpace, setDecor, setAlign
getColor, getOpa, getFont, getLetterSpace, getLineSpace, getDecor, getAlign
void* font = widget->getFont(18, "", 1);
widget->getStyle()->p_text
->setColor(0x222222)
->setOpa(255)
->setFont(font)
->setLetterSpace(1)
->setLineSpace(4)
->setDecor(0)
->setAlign(2);
setFont(nullptr) 静默不做任何事,不会恢复默认字体。字体指针必须持续有效。
方法:
setTop, setBottom, setLeft, setRight, setAll,
setRow, setColumn, setHor, setVer, setGap,
getTop, getBottom, getLeft, getRight, getRow, getColumn
widget->getStyle()->p_pad
->setAll(8)
->setRow(6)
->setColumn(10);
setHor/setVer/setGap 是 LVGL 组合 setter,但没有对应组合 getter,读取用左右/上下/row/column。
方法:setX、setY、getX、getY。
widget->getStyle()->p_translate
->setX(4, WidgetState::PRESSED)
->setY(2, WidgetState::PRESSED);
translate 影响绘制位置,不更新布局占位或 STTWidget 坐标缓存。
方法:
setWidth, setHeight, setAngle, setPivotX, setPivotY, setZoom
getWidth, getHeight, getAngle, getPivotX, getPivotY, getZoom
widget->getStyle()->p_transform
->setPivotX(50)
->setPivotY(50)
->setAngle(30.0f)
->setZoom(1.2f)
->setWidth(4)
->setHeight(4);
角度内部乘 10,zoom 乘 256;get 使用相反换算。没有范围校验。
方法:
setColor, setOpa, setWidth, setSide, setPost
getColor, getOpa, getWidth, getSide, getPost
widget->getStyle()->p_border
->setColor(0xcccccc)
->setOpa(255)
->setWidth(1)
->setSide(1 | 2 | 4 | 8)
->setPost(false);
side 位值为下 1、上 2、左 4、右 8。post 表示延后绘制边框。
写方法:
setFromDsc, setColor, setOpa, setGradColor, setGradDir,
setMainStop, setGradStop, setImgSrc, setImgOpa,
setImgRecolor, setImgRecolorOpa, setImgTiled
读方法:
getColor, getOpa, getGradColor, getGradDir,
getMainStop, getGradStop, getImgSrc, getImgOpa,
getImgRecolor, getImgRecolorFiltered, getImgRecolorOpa,
getImgTiled
widget->getStyle()->p_bg
->setColor(0xffffff)
->setGradColor(0xe8f2ff)
->setGradDir(1)
->setMainStop(0.0f)
->setGradStop(1.0f)
->setOpa(255);
MainStop/GradStop 以 0.0..1.0 输入,内部乘 255,不做夹取。setFromDsc 只复制背景相关字段,不复制 radius、border、outline、shadow 等。
图片:
widget->getStyle()->p_bg
->setImgSrc("res/bg.png")
->setImgOpa(255)
->setImgRecolor(0xffffff)
->setImgRecolorOpa(0)
->setImgTiled(false);
路径/描述符生命周期由调用方和 LVGL 资源系统负责。
配置与读取:
auto* scroll = widget->getStyle()->p_scrollbar;
scroll->setMode(3);
scroll->setDir(12);
scroll->setSnapX(0);
scroll->setSnapY(3);
uint8_t mode = scroll->getMode();
uint8_t dir = scroll->getDir();
uint8_t snapX = scroll->getSnapX();
uint8_t snapY = scroll->getSnapY();
位置/范围:
int x = scroll->getX();
int y = scroll->getY();
int top = scroll->getTop();
int bottom = scroll->getBottom();
int left = scroll->getLeft();
int right = scroll->getRight();
LvPoint end;
scroll->getEnd(&end);
滚动:
scroll->scrollBy(20, 0, LV_ANIM_ON);
scroll->scrollTo(100, 0, LV_ANIM_OFF);
scroll->scrollToX(40, LV_ANIM_ON);
scroll->scrollToY(80, LV_ANIM_ON);
scroll->scrollToView(LV_ANIM_ON);
scroll->scrollToViewRecursive(LV_ANIM_ON);
辅助:
bool active = scroll->isScrolling();
scroll->updateSnap(LV_ANIM_ON);
LvArea horizontal, vertical;
scroll->getArea(&horizontal, &vertical);
scroll->invalidate();
scroll->reAdjust(LV_ANIM_ON);
头文件对 reAdjust 的 anim_en 文案与 LVGL 常规枚举可能相反;实现直接强转 lv_anim_enable_t,应使用 LV_ANIM_OFF/ON 常量,不写 0/1 注释语义。
STTStyleProp 是所有子属性基类:
STTStyleProp(void* obj), attach(void* obj), selector, protected object
attach 只是替换底层 object,不校验类型/有效性。
STTStyleHelper:
STTStyle* a = STTStyleHelper::attach(widget, 0);
STTStyle* b = STTStyleHelper::attach(rawLvObject, 1);
flag=0 把 obj 当 STTWidget* 并读取 object;非 0 直接当 lv_obj_t*。类型传错会崩溃。p_style 字段未用于返回实例管理。
container->setLayout(STTLayout::FlexLayout());
STTLayout::setFlexFlow(container, 0);
STTLayout::setFlexAlign(container, 0, 0, 2, 0);
STTLayout::setFlexGlow(child, 0, 1);
API:
| 方法 | 说明 |
|---|---|
| FlexLayout | 返回 LV_LAYOUT_FLEX |
| GridLayout | 返回 LV_LAYOUT_GRID |
| setFlexFlow(obj, style) | obj 固定按 STTWidget* |
| setFlexFlow(obj, objtype, style) | objtype=0 STTWidget,其他为 lv_obj_t |
| setFlexAlign | 设置 main/cross/track 对齐 |
| setFlexGlow | 名称拼写为 Glow,实际调用 lv_obj_set_flex_grow |
flow style:0 行、4 行换行、8 行反向、12 行换行反向;1 列、5 列换列、9 列反向、13 列换列反向。
GridLayout 只返回布局 ID,本头文件没有网格描述符配置封装,复杂 Grid 仍需 LVGL API。