4、样式属性详解(下):文本属性(字体、颜色、对齐、行高)、阴影与轮廓
好,咱们接着聊。上一节我们把背景和边框讲透了,这一节轮到文本和特效了。说实话,文本属性在嵌入式UI里特别容易被忽视——很多人觉得「不就是显示几个字嘛」。但我在项目里吃过不少亏,比如字体没对齐导致界面看起来歪歪扭扭,或者阴影画得太重把性能拖垮了。今天咱们就把这些坑一个个填上。
4.1 文本属性:字体的灵魂三问
LVGL的文本控制,核心就三个东西:用什么字体、什么颜色、怎么对齐。咱们一个一个来。
4.1.1 字体设置:选对字体,事半功倍
字体用 lv_style_set_text_font() 来设置。我个人习惯把字体定义成全局变量,方便复用。
lv_style_set_text_font(&style_btn, &lv_font_montserrat_14);
这里要注意:LVGL的字体是位图字体,不是TrueType。什么意思呢?就是每个字都提前画好了像素点。好处是渲染快,坏处是——你没法随便放大缩小。我曾经在项目里把字体设成24号,结果发现中文字体没包含,显示出来全是方框。嗯,那叫一个尴尬。
4.1.2 文本颜色:不只是好看
颜色设置很简单:
lv_style_set_text_color(&style, lv_color_hex(0x333333));
lv_style_set_text_opa(&style, LV_OPA_80); // 透明度,80%
但我想多说一句:文本颜色和背景的对比度一定要够。你想想看,如果背景是浅灰色,文字也是浅灰色,用户根本看不清。我一般建议对比度至少4.5:1,这是WCAG无障碍标准的要求。虽然咱们做嵌入式UI不一定非要过认证,但用户体验是实打实的。
4.1.3 文本对齐:左中右,你选哪个?
对齐方式有四种:左对齐、居中对齐、右对齐、两端对齐。用这个宏:
lv_style_set_text_align(&style, LV_TEXT_ALIGN_CENTER);
这里有个细节:对齐是相对于对象的宽度,不是屏幕。比如一个按钮宽200像素,你设了居中对齐,文字就会在按钮中间显示。我见过有人把对齐设成左对齐,但按钮宽度设得特别大,结果文字跑到最左边,看起来像没对齐一样——其实是对齐了,只是对象太宽了。
4.1.4 行高:别让文字挤在一起
行高用 lv_style_set_text_line_space() 控制。默认是0,也就是行与行之间没有额外间距。但多行文本时,我建议至少加4-6像素。
lv_style_set_text_line_space(&style, 6);
为什么?因为汉字本身比较高,如果行间距为0,两行文字几乎贴在一起,阅读体验很差。我在做天气显示界面时,温度、湿度、风速三行信息,加了8像素行高后,整个界面清爽多了。
4.2 阴影:给UI加点立体感
阴影是LVGL 8.0之后才完善的特性。用好了,界面瞬间有层次感;用不好,就是一团糊。
4.2.1 阴影的基本参数
阴影有四个核心参数:
| 参数 | 函数 | 说明 |
|---|---|---|
| 宽度 | lv_style_set_shadow_width() |
阴影的模糊范围,0表示无阴影 |
| 偏移X | lv_style_set_shadow_ofs_x() |
水平偏移,正数向右 |
| 偏移Y | lv_style_set_shadow_ofs_y() |
垂直偏移,正数向下 |
| 颜色 | lv_style_set_shadow_color() |
阴影颜色,通常用半透明黑 |
一个典型的按钮阴影设置:
lv_style_set_shadow_width(&style, 10);
lv_style_set_shadow_ofs_x(&style, 2);
lv_style_set_shadow_ofs_y(&style, 4);
lv_style_set_shadow_color(&style, lv_color_hex(0x000000));
lv_style_set_shadow_opa(&style, 30); // 透明度30%
4.2.2 阴影的坑:性能与显示
我曾经在一个项目里给每个按钮都加了10像素阴影,结果界面滑动时明显卡顿。后来发现,阴影的模糊计算在低端MCU上很吃资源。解决办法有两个:
- 减少阴影宽度:5像素以内,性能影响小很多
- 用图片代替阴影:预渲染一张阴影图片,用
lv_img显示,完全不消耗CPU
另外要注意:阴影是绘制在对象外部的。如果你的对象紧贴着屏幕边缘,阴影可能会被裁剪掉。我建议给父容器留出至少阴影宽度+偏移量的边距。
4.3 轮廓:另一种「边框」
轮廓(Outline)和边框(Border)很像,但有本质区别:轮廓不占布局空间。什么意思呢?边框会挤占内部内容的空间,但轮廓是画在对象外部的,不影响内部布局。
4.3.1 轮廓的典型用法
轮廓最适合做焦点指示。比如按钮被选中时,加一个轮廓高亮:
lv_style_set_outline_width(&style_focus, 2);
lv_style_set_outline_color(&style_focus, lv_color_hex(0x007AFF));
lv_style_set_outline_pad(&style_focus, 3); // 轮廓与对象的间距
你看,轮廓和对象之间还有3像素的间距,这样不会和边框重叠。我在做遥控器界面时,就用轮廓来标识当前选中的按钮,效果比改背景色好多了——因为背景色变了会让人觉得按钮「按下了」,而轮廓只是「被选中了」,语义更清晰。
4.3.2 轮廓的注意事项
轮廓有几个限制:
- 不支持圆角:轮廓始终是直角矩形,即使对象有圆角
- 不支持单边:要么四边都有,要么都没有
- 会被父容器裁剪:如果父容器设置了
overflow: hidden,轮廓超出部分会被切掉
4.4 综合示例:一个带阴影和轮廓的卡片
咱们把今天学的串起来,做一个信息卡片:
/* 卡片基础样式 */
lv_style_t style_card;
lv_style_init(&style_card);
lv_style_set_bg_color(&style_card, lv_color_hex(0xFFFFFF));
lv_style_set_radius(&style_card, 8);
lv_style_set_pad_all(&style_card, 16);
/* 阴影:让卡片浮起来 */
lv_style_set_shadow_width(&style_card, 12);
lv_style_set_shadow_ofs_x(&style_card, 0);
lv_style_set_shadow_ofs_y(&style_card, 4);
lv_style_set_shadow_color(&style_card, lv_color_hex(0x000000));
lv_style_set_shadow_opa(&style_card, 25);
/* 标题文本样式 */
lv_style_t style_title;
lv_style_init(&style_title);
lv_style_set_text_font(&style_title, &lv_font_montserrat_16);
lv_style_set_text_color(&style_title, lv_color_hex(0x1A1A1A));
lv_style_set_text_align(&style_title, LV_TEXT_ALIGN_LEFT);
/* 内容文本样式 */
lv_style_t style_content;
lv_style_init(&style_content);
lv_style_set_text_font(&style_content, &lv_font_montserrat_12);
lv_style_set_text_color(&style_content, lv_color_hex(0x666666));
lv_style_set_text_line_space(&style_content, 6);
/* 焦点轮廓样式 */
lv_style_t style_focus;
lv_style_init(&style_focus);
lv_style_set_outline_width(&style_focus, 2);
lv_style_set_outline_color(&style_focus, lv_color_hex(0x007AFF));
lv_style_set_outline_pad(&style_focus, 4);
这个卡片用阴影制造了「浮起」的效果,文本用了不同的字体大小和颜色来区分层级,焦点时还有蓝色轮廓。嗯,基本够用了。
4.5 小结
今天的内容其实就两件事:文本怎么控制和特效怎么加。文本方面,字体、颜色、对齐、行高这四个参数,掌握了就能应付90%的场景。阴影和轮廓是锦上添花的东西,但用好了能让UI质感提升一个档次。
最后提醒一句:不要为了特效而特效。我见过有人给每个控件都加阴影,结果界面看起来像一堆纸片堆在一起,反而没有重点。适可而止,才是高手。
下一节咱们讲过渡动画,那才是真正让UI「活」起来的东西。到时候见。