3、样式属性详解(中):边框属性(宽度、颜色、样式、边距)

好,咱们接着聊样式属性。上一节我们把背景和圆角讲透了,这一节轮到边框了。说实话,边框在嵌入式UI里是个「又爱又恨」的东西——用好了能提升质感,用不好就是灾难。我早期做的一个工业控制面板项目,就因为边框没处理好,被客户吐槽「像玩具」。

边框属性在LVGL里其实就四个核心维度:宽度、颜色、样式、边距。别小看这四个参数,组合起来能玩出花来。咱们一个一个拆。

3.1 边框宽度(border_width)

边框宽度,说白了就是边框有多粗。单位是像素,默认是0(也就是不显示)。

/* 设置边框宽度为2像素 */
lv_obj_set_style_border_width(obj, 2, LV_STATE_DEFAULT);

我个人习惯把边框宽度控制在1~4像素之间。太细了看不清,太粗了又显得笨重。你想想看,一个按钮如果边框8像素,那视觉上会非常突兀。

我的经验:在触摸屏上,边框宽度建议至少2像素。因为触摸屏的显示精度有限,1像素的边框在强光下几乎看不见。我曾经在一个户外设备上吃过这个亏,后来统一改成了2像素。

3.2 边框颜色(border_color)

边框颜色就简单了,直接给个颜色值。但这里有个坑——边框颜色和背景颜色是叠加的

/* 设置边框颜色为红色 */
lv_obj_set_style_border_color(obj, lv_color_hex(0xFF0000), LV_STATE_DEFAULT);

嗯,这里要注意:如果你设置了边框宽度为0,那颜色设了也白设。我见过不少新手在这上面浪费时间,调了半天颜色发现没变化,最后发现是宽度没开。

场景 推荐边框颜色 说明
普通按钮 比背景深20% 增加层次感
选中状态 主题色 突出显示
错误提示 红色系 警示作用
禁用状态 灰色系 降低视觉权重

3.3 边框样式(border_opa 和 border_side)

边框样式这块,LVGL提供了两个关键属性:透明度(border_opa)和显示方向(border_side)。

3.3.1 边框透明度

/* 设置边框半透明 */
lv_obj_set_style_border_opa(obj, LV_OPA_50, LV_STATE_DEFAULT);

透明度这个属性,说实话我用的不多。但在做「悬浮效果」时特别好用——比如一个卡片,正常状态边框透明度80,按下时变成100,视觉上就有「浮起来」的感觉。

3.3.2 边框显示方向

这个就厉害了。LVGL允许你只显示某几条边,而不是四边全显示。

/* 只显示底部边框 */
lv_obj_set_style_border_side(obj, LV_BORDER_SIDE_BOTTOM, LV_STATE_DEFAULT);

/* 显示左右边框 */
lv_obj_set_style_border_side(obj, LV_BORDER_SIDE_LEFT | LV_BORDER_SIDE_RIGHT, LV_STATE_DEFAULT);
核心要点:边框方向的可选值有:
LV_BORDER_SIDE_NONE(无边框)、LV_BORDER_SIDE_TOP、LV_BORDER_SIDE_BOTTOM、LV_BORDER_SIDE_LEFT、LV_BORDER_SIDE_RIGHT、LV_BORDER_SIDE_FULL(全显示)、LV_BORDER_SIDE_INTERNAL(内部边框,用于表格等)。

为什么需要这个?我举个例子:做列表项时,通常只需要底部一条分割线。如果四边都画,反而显得杂乱。用LV_BORDER_SIDE_BOTTOM就能完美实现「分割线效果」。

3.4 边框边距(border_width 与 padding 的关系)

这里要澄清一个概念:LVGL里没有独立的「边框边距」属性。边框是紧贴着内容区域的,它的「边距」实际上是通过padding来控制的。

说白了,边框的位置是在padding的外边界上。如果你设置了padding:10,边框宽度:2,那实际占用的空间是:内容区 + padding(10) + 边框(2)。

/* 示例:带边框的卡片 */
lv_obj_t * card = lv_obj_create(parent);
lv_obj_set_size(card, 200, 100);
lv_obj_set_style_pad_all(card, 10, LV_STATE_DEFAULT);      /* 内边距10 */
lv_obj_set_style_border_width(card, 2, LV_STATE_DEFAULT);   /* 边框宽度2 */
lv_obj_set_style_border_color(card, lv_color_hex(0xCCCCCC), LV_STATE_DEFAULT);
避坑指南:我曾经在一个项目中,为了给边框留空间,手动把控件尺寸调大了。结果布局全乱了。后来才发现,LVGL的边框是向外扩展的,不会影响内容区大小。所以千万别手动去调尺寸来「适应边框」。

3.5 实战组合:一个带边框的卡片

好了,理论说完了,咱们来点实际的。下面这个例子,是我在智能家居面板项目中常用的卡片样式:

/* 创建一个卡片 */
lv_obj_t * card = lv_obj_create(parent);
lv_obj_set_size(card, 150, 80);
lv_obj_center(card);

/* 背景和圆角 */
lv_obj_set_style_bg_color(card, lv_color_hex(0xFFFFFF), LV_STATE_DEFAULT);
lv_obj_set_style_radius(card, 8, LV_STATE_DEFAULT);

/* 边框设置 */
lv_obj_set_style_border_width(card, 2, LV_STATE_DEFAULT);
lv_obj_set_style_border_color(card, lv_color_hex(0x2196F3), LV_STATE_DEFAULT);
lv_obj_set_style_border_side(card, LV_BORDER_SIDE_LEFT, LV_STATE_DEFAULT);  /* 只有左边有蓝色边框 */

/* 内边距 */
lv_obj_set_style_pad_all(card, 12, LV_STATE_DEFAULT);

/* 添加文字 */
lv_obj_t * label = lv_label_create(card);
lv_label_set_text(label, "温度: 26°C");
lv_obj_center(label);

这个卡片的效果是:白色背景,左边有一条2像素的蓝色竖线,文字居中。看起来非常清爽,适合做仪表盘上的数据卡片。

我的习惯:做卡片时,我通常只保留左边或底部的边框,配合圆角,视觉上更现代。全边框的卡片容易显得「框死」,不够灵动。

3.6 状态联动:边框与交互

边框在交互状态下的变化,是提升用户体验的关键。我建议你至少为以下状态设置不同的边框:

  • 默认状态:浅色边框,宽度1~2像素
  • 按下/选中状态:主题色边框,宽度2~3像素
  • 禁用状态:灰色边框,透明度降低
/* 默认状态 */
lv_obj_set_style_border_width(btn, 1, LV_STATE_DEFAULT);
lv_obj_set_style_border_color(btn, lv_color_hex(0xCCCCCC), LV_STATE_DEFAULT);

/* 按下状态 */
lv_obj_set_style_border_width(btn, 2, LV_STATE_PRESSED);
lv_obj_set_style_border_color(btn, lv_color_hex(0x2196F3), LV_STATE_PRESSED);

你看,代码很简单,但效果立竿见影。用户按下去时,边框变粗、变色,反馈非常明确。

3.7 小结

边框属性这块,核心就记住三点:

  1. 宽度决定存在感——太细看不见,太粗显笨重
  2. 颜色和方向决定风格——单边边框更现代,全边框更传统
  3. 边框不占内容空间——别傻傻地去调尺寸

下一节我们会讲阴影和轮廓属性,这两个是「高级感」的关键。到时候我会分享一个我做车载HUD时用到的阴影技巧,保证让你眼前一亮。