1、Linux常用命令 1.1、Linux命令初體驗 在日常使用過程當中經常使用到的命令有如下幾種 命令 對應英文 作用 ls [目錄名] list 查看當前目錄下的內容 pwd print work directory 查看當前所在目錄 cd [目錄名] change directory 切換目錄 ...
LVGL樣式
LVGL樣式概述
創建樣式
在 LVGL 中,樣式都是以對象的方式存在,一個對象可以描述一種樣式。每個控制項都可以獨立添加樣式,創建的樣式之間互不影響。
可以使用 lv_style_t
類型創建一個樣式並初始化:
static lv_style_t style;
lv_style_init(&style);
樣式是延遲渲染的,因此需要使用 static
存儲類別說明符或將其聲明為全局變數。
樣式是多方面的,不僅包括顏色和形狀,還包括邊距、邊框,甚至動畫變換效果等細節。
LVGL 中的樣式從 CSS 中吸取了很多靈感,因此對樣式的操作都類似 CSS
接下來,可以對得到的樣式對象設置一些樣式規則:
/* ... create and init style ... */
lv_style_set_radius(&style_btn_safe, 15);
lv_style_set_bg_opa(&style_btn_safe, LV_OPA_COVER);
lv_style_set_bg_color(&style_btn_safe, lv_palette_main(LV_PALETTE_GREEN));
lv_style_set_border_width(&style_btn_safe, 5);
所有的設置樣式函數都是 lv_style_set_...()
形式,完整的樣式規則將在之後介紹。未指定的樣式規則將保持控制項的預設樣式。
然後就可以將樣式分配給控制項,例如,以下創建了一個按鈕並利用 lv_obj_add_style()
函數設置其樣式為剛纔創建的樣式了:
lv_obj_t* btn = lv_btn_create(lv_scr_act());
lv_obj_set_size(btn, 120, 50);
lv_obj_t* label = lv_label_create(btn);
lv_label_set_text(label, "Button");
lv_obj_add_style(btn, &style_btn_safe, 0);
這樣按鈕的外觀就會被改變了,效果為:
以上修改了按鈕的顏色,如果對顏色的創建過程不太理解也不要緊,以後會介紹顏色的代碼描述。可以簡單地將 GREEN 改成其它顏色名來改變不同的顏色。設置樣式的函數最後有一個參數 0
,它代表的是樣式的選擇器,將會在接下來介紹。
一個文件內可以創建多種不同的樣式對象,這樣同一個界面中按鈕可以表現出多種不同的樣式。
樣式的級聯
所謂“級聯”(cascading),指的是將多個樣式分配給一個對象。此時如果多個樣式間設置的樣式屬性有重覆,那麼將使用最後設置的樣式值。也就是說,後設置的樣式具有更高的優先順序。
控制項在創建時可以視為同時添加了一個預設的樣式,因此在代碼中指定的任意樣式都會覆蓋預設的樣式。
還有一種特殊的局部樣式(local styles),局部樣式具有最高的優先順序,但只對單個控制項有效。局部樣式的創建類似如下:
lv_obj_set_style_bg_color(btn, lv_palette_main(LV_PALETTE_RED), 0);
它們都是 lv_obj_set_style_...()
形式的函數。
局部樣式一旦被設置,只能再次通過局部樣式修改回來。因此,局部樣式需要謹慎使用。
選擇器
LVGL 的選擇器(selector)與 CSS 不同。在 CSS 中,樣式通過選擇器選擇需要作用的元素;而 LVGL 中,樣式通過選擇器作用於控制項的部分。
要明白什麼是控制項的部分,需要分析控制項的組成。例如,以下代碼可以創建一個滑塊(slider)控制項:
lv_obj_t* slider01 = lv_slider_create(lv_scr_act());
滑塊是一種調整類型的控制項,用戶可以通過拖動它的把手(knob)來調節滑塊當前的數值。滑塊預設的表現形式為:
仔細觀察滑塊的組成,滑塊可以由主體外形、把手(knob)和進度指示條(indicator)組成。可以通過選擇器單獨設置這三個構成部分的樣式。例如,假設需要更改這三個部分的樣式,就可以通過選擇器分別指定修改的結構:
static lv_style_t style_slider_main;
lv_style_init(&style_slider_main);
lv_style_set_bg_opa(&style_slider_main, LV_OPA_COVER);
lv_style_set_bg_color(&style_slider_main, lv_palette_main(LV_PALETTE_YELLOW));
/* using selectors */
lv_obj_add_style(slider01, &style_slider_main, LV_PART_MAIN);
lv_obj_set_style_radius(slider01, 0, LV_PART_KNOB);
lv_obj_set_style_bg_color(slider01, lv_palette_main(LV_PALETTE_RED), LV_PART_INDICATOR);
這裡分別使用全局樣式和局部樣式修改控制項的各個部分。修改之後,把手部分變成了方形,主體和進度進度的顏色都發生了變化:
選擇器的一個更妙的用途是和控制項狀態做按位或運算,從而可以修改某個部分在某個狀態下的樣式。例如,選擇器
lv_obj_add_style(slider01, &style_slider_main,
LV_PART_MAIN | LV_STATE_PRESSED);
使滑塊的主體只有在按下時才會使用該樣式(顏色被改變):
LVGL 的選擇器在表現形式上效果非常像 CSS 的偽元素和偽類選擇器。
滑塊在拖動過程中,會不斷觸發 LV_EVENT_VALUE_CHANGED
事件,可以使用函數
static inline int32_t lv_slider_get_value(const lv_obj_t* obj);
獲取當前獲取的滑塊數值(介於 0~100 )。更多的滑塊 API 可以參考官方文檔的介紹。
接下來詳細地介紹樣式可以設置的一些屬性。
樣式屬性
尺寸和位置
要理解尺寸和位置是如何起作用的,首先要理解 LVGL 的盒子模型。官方文檔給出了一張圖,可以很好地描述一個控制項的框架結構:
在設置尺寸的時候,長和寬指的是包括邊框(border)厚度的長寬,也就是不包括輪廓(outline)的總長寬。
在設置位置的時候,設置的坐標指的是 border 左上角相對父容器的 Content area 的坐標,也就是說如果設置坐標為 0 的話,輪廓(outline)可能會被父容器的邊框(border)遮蓋。
下表總結了尺寸與位置有關的可用屬性有:
屬性 | 描述 | 預設值 |
---|---|---|
width |
寬度 | 由控制項類別決定 |
min_width |
最小寬度 | 0 |
max_width |
最大寬度 | 屏幕的寬度 |
height |
高度 | 由控制項類別決定 |
min_height |
最小寬度 | 0 |
max_height |
最大寬度 | 屏幕的高度 |
align |
對齊方式 | 左上方 |
x |
對齊後在水平方向的偏移量 | 0 |
y |
對齊後在豎直方向的偏移量 | 0 |
註意這裡有一個最小或最大的寬度和高度,在上一節介紹 flex 和 grid 佈局時就展示過控制項寬度隨佈局自動調整的情況,因此可以給它們提供一個閾值防止過大或過小。
不過上一節還有一個地方沒有提到:在設置寬度和高度時,除了使用確定的數值外,還可以使用百分比值 lv_pct(x)
來設置控制項相對父容器的 Content area 的大小或位置。例如,樣式
lv_style_set_width(&style, lv_pct(25));
lv_style_set_x(&style, lv_pct(50));
可以讓一個控制項的水平尺寸占據父容器的 1/2~3/4 的位置:
對於父容器而言,還可以使用 LV_SIZE_CONTENT
特殊單位調整其尺寸至可以容納所有包含控制項的合適值。例如,按鈕就是一個這樣的容器,它的預設樣式就通過該值使得其寬度和高度可以自動適應包含的標簽尺寸。
邊框和邊距
上圖展示的文本框就有一個深灰色的邊框。邊框就無需額外描述了,與邊框有關的樣式屬性有:
屬性 | 描述 | 預設值 |
---|---|---|
border_width |
邊框寬度,只能用絕對寬度描述 | 0 |
border_side |
繪製哪些部分的邊框 | LV_SIDE_ALL |
border_post |
繪製順序,設置 true 表示包含的子控制項繪製完成了再繪製邊框 |
false |
... | 與顏色有關的屬性將在之後介紹 |
邊框和主體部分之間被邊距(padding)隔開。和邊距有關的樣式屬性有:
屬性 | 描述 | 預設值 |
---|---|---|
pad_top | 上邊距 | 0 |
pad_bottom | 下邊距 | 0 |
pad_left | 左邊距 | 0 |
pad_right | 右邊距 | 0 |
pad_row | 當控制項擁有佈局時,每行間的間距 | 0 |
pad_column | 當控制項擁有佈局時,每列間的間距 | 0 |
不過在設置佈局時,還提供了幾個簡寫屬性:可以使用 ...pad_all()
一併設置上下左右的邊距;或使用 ...pad_hor()
和 ...pad_ver()
設置水平和垂直的邊距;還可以使用 ...pad_gap()
設置行和列的間距。
輪廓
輪廓(outline)類似邊框,但輪廓並不算在一個控制項的主體內,因此設置坐標、尺寸等屬性時都不包含輪廓的尺寸。
輪廓可設置的屬性遠比邊框少。下表列出了輪廓的一些屬性:
屬性 | 描述 | 預設值 |
---|---|---|
outline_width |
輪廓寬度 | 0 |
outline_pad |
輪廓到主體的間距 | 0 |
... | 與顏色有關的屬性將在之後介紹 |
輪廓和邊框最根本的差異是兩者不是同一個東西,因此可以在同一個元素同時使用不同樣式的輪廓的邊框來實現一些有趣的效果,例如:
lv_style_set_radius(&style, 0);
lv_style_set_border_color(&style, lv_palette_main(LV_PALETTE_GREY));
lv_style_set_border_width(&style, 5);
lv_style_set_border_opa(&style, LV_OPA_COVER);
lv_style_set_border_side(&style, LV_BORDER_SIDE_BOTTOM | LV_BORDER_SIDE_RIGHT);
lv_style_set_outline_width(&style, 4);
lv_style_set_outline_pad(&style, 1);
lv_style_set_outline_color(&style, lv_palette_lighten(LV_PALETTE_GREY, 1));
表現效果為:
陰影
陰影可以使控制項看起來有立體感。下表列出了設置陰影的一些屬性:
屬性 | 描述 | 預設值 |
---|---|---|
shadow_width |
設置陰影的模糊半徑 | 0 |
shadow_ofs_x |
設置陰影的水平偏移量 | 0 |
shadow_ofs_y |
設置陰影的垂直偏移量 | 0 |
shadow_spread |
設置陰影的放大量 | 0 |
... | 與顏色有關的屬性將在之後介紹 |
例如,以下設置模糊半徑為 50 的藍色陰影:
lv_style_set_shadow_width(&style, 50);
lv_style_set_shadow_color(&style, lv_palette_main(LV_PALETTE_BLUE));
效果為:
以下設置放大有偏移的紅色陰影:
lv_style_shadow_color(&style, lv_palette_main(LV_PALETTE_RED))
lv_style_set_shadow_width(&style, 15)
lv_style_set_shadow_ofs_x(&style, 10)
lv_style_set_shadow_ofs_y(&style, 20)
lv_style_set_shadow_spread(&style, 10)
效果為:
LVGL 中無法給同一個控制項設置多個陰影疊加,從而實現更複雜的效果,這是比較可惜的一點。
文本樣式
在創建控制項時經常要使用文字,下表列出了能影響文字效果的一些屬性:
屬性 | 描述 | 預設值 |
---|---|---|
text_font |
設置文字的字體 | 預設字體 |
text_letter_space |
字元間隔 | 0 |
text_line_space |
設置多行文本的行間距 | 0 |
text_decor |
設置文本裝飾(下劃線或刪除線) | LV_TEXT_DECOR_NONE |
text_align |
設置文本對齊方式 | LV_TEXT_ALIGN_AUTO |
... | 與顏色有關的屬性將在之後介紹 |
需要註意的是,文本的樣式是可繼承的,意思是如果子控制項沒有特別指定的話,它會使用父容器設置的文本樣式。
在一段文本內可能存在許多種樣式,對此,可以使用類似 CSS 的 span 來拆分樣式在文本內的作用域。為了創建 span ,首先需要創建一個 span-group :
lv_obj_t* spangroup = lv_spangroup_create(lv_scr_act());
lv_obj_set_size(spangroup, 160, LV_SIZE_CONTENT);
創建的 span-group 和一般的控制項沒什麼區別,可以給它添加一些樣式:
lv_obj_set_style_border_color(spangroup, lv_palette_main(LV_PALETTE_BLUE), 0);
lv_obj_set_style_border_width(spangroup, 1, 0);
lv_obj_set_style_pad_all(spangroup, 5, 0);
span-group 提供的以下函數使得它相比標簽更適合用來處理大段的文本:
函數 | 介紹 |
---|---|
lv_spangroup_set_align(obj, align) |
設置文本的對齊 |
lv_spangroup_set_overflow(obj, overflow) |
控制溢出文本的處理方式 |
lv_spangroup_set_indent(obj, indent) |
設置文本的首行縮進,單位為像素 |
lv_spangroup_set_mode(obj, mode) |
設置對多行文本的折行處理,可以參見枚舉 lv_span_mode_t |
有了 span-group 以後,可以使用以下代碼從中創建一個 span 並設置文本:
lv_span_t* span = lv_spangroup_new_span(spangroup);
lv_span_set_text(span, "LVGL is an open-source graphics library");
每一個 span 都提供了一個獨立的樣式介面,可以單獨設置範圍內文本的樣式:
lv_style_set_text_color(&span->style, lv_palette_main(LV_PALETTE_BLUE));
一個 span-group 可以創建多個 span ,並且它們的樣式效果互不影響:
span = lv_spangroup_new_span(spangroup);
lv_span_set_text(span, "providing everything");
lv_style_set_text_decor(&span->style, LV_TEXT_DECOR_UNDERLINE);
lv_style_set_text_font(&span->style, &lv_font_montserrat_20);
/* ... */
span = lv_spangroup_new_span(spangroup);
lv_span_set_text(span, "to create embedded GUI");
效果為:
可以註意到預設的 span-group 是沒什麼樣式的。span-group 還有很多的 API ,具體可以參照官方文檔的相關介紹。
其它樣式
下表列出了一些其它的樣式屬性:
屬性 | 描述 | 預設值 |
---|---|---|
radius |
設置控制項的圓角,該屬性會一併影響邊框和輪廓 | 0,即無圓角 |
clip_corner |
如果有圓角,是否要將 Content-aera 超出圓角的部分去除 | 否 |
layout |
設置控制項的佈局方式 | 0 |
base_dir |
設置文字的書寫方向,它會同時影響佈局的方向 | 預設書寫方向 |
... | 與顏色有關的屬性將在之後介紹 |
在設置半徑時可以使用百分數,例如 lv_pct(50)
將使控制項變成圓形。
以上列出了大部分的樣式屬性,但是除了顏色外還有許多樣式沒有介紹,例如變換、動畫、漸變等,這些留到之後介紹。LVGL 中還存在一些特殊的樣式,它們是為相應的控制項設計的,接下來介紹這些控制項及樣式。
基本圖形:直線和弧線
直線
LVGL 中的直線(line)實際上指的是折線,因為它可以一次性連續繪製多條相接的線段。為了繪製折線,首先要準備一些端點的坐標:
static lv_point_t line_points[] = { {217, 36}, {35, 49}, {281, 163}, {110, 162}, {257, 111} };
然後可以通過這些端點來創建折線:
lv_obj_t* line1 = lv_line_create(lv_scr_act());
lv_line_set_points(line1, line_points, 5);
效果為:
創建的折線作為一個整體,實際上也是一個控制項,當然可以給它加上各種屬性:
static lv_style_t style_line;
lv_style_init(&style_line);
lv_style_set_align(&style_line, LV_ALIGN_TOP_MID);
lv_style_set_border_width(&style_line, 4);
lv_obj_add_style(line01, &style_line, 0);
效果為:
折線擁有一些特殊的樣式屬性,是其它控制項所沒有的。下表列出了折線的特殊屬性:
屬性 | 描述 | 預設值 |
---|---|---|
line_width |
設置線段寬度 | 0 |
line_dash_width |
設置虛線實部分的距離 | 0 |
line_dash_gap |
設置虛線虛部分的距離 | 0 |
line_rounded |
設置線段端點是否為圓角 | 否 |
line_color |
設置線段顏色 | 黑色 |
line_opa |
設置顏色透明度 | 不透明 |
註意,虛線只對水平和垂直的線段有效,並且只有兩個屬性都不為 0 才有虛線的效果。
例如,樣式:
lv_style_set_line_color(&style_line, lv_palette_main(LV_PALETTE_BLUE));
lv_style_set_line_width(&style_line, 8);
表現效果為:
如果再添加上:
lv_style_set_line_dash_width(&style_line, 10)
lv_style_set_line_dash_gap(&style_line, 5)
lv_style_set_line_rounded(&style_line, true);
那麼效果就變成:
關於折線還有一個函數 lv_line_set_y_invert(lv_obj_t *obj, bool en)
可以用來控制繪製的折線垂直翻轉(即翻轉 y 軸)。除此之外折線並沒有什麼可以介紹的。在後續還會介紹圖表,可以繪製更美觀的折線效果。
圓弧
LVGL 中的圓弧(arc)儘管和直線同屬於基礎控制項,但圓弧的功能遠比直線豐富,甚至 API 比起滑塊這些複雜的控制項都多。
首先簡單創建一個圓弧,查看它的預設效果:
lv_obj_t* arc01 = lv_arc_create(lv_scr_act());
預設的效果為:
可以看出圓弧的在預設情況下,它的表現形式實際上就是弧形的滑塊。如果想要得到純粹的圓弧,可以將圓弧的把手刪除:
lv_obj_remove_style(arc01, NULL, LV_PART_KNOB);
lv_obj_clear_flag(arc01, LV_OBJ_FLAG_CLICKABLE);
這裡做了兩件事:首先是將把手的樣式刪除,這裡第二個參數 NULL
表示刪去全部樣式;其次將圓弧的可點擊標誌位清除,使它不再能接收用戶的點擊事件。這樣圓弧看起來就純粹多了:
還可以進一步刪去圓弧的指示條(indicator),讓它更像傳統的圓弧。
預設的圓弧是開口向下的 270° 圓弧。為了設置圓弧的形狀,可以使用函數
void lv_arc_set_angles(lv_obj_t *obj, uint16_t start, uint16_t end);
void lv_arc_set_bg_angles(lv_obj_t *obj, uint16_t start, uint16_t end);
分別修改前景和背景的圓弧起止範圍,單位為角度。註意,圓弧的角度 0° 是正右方向,90° 是正下方向,以此類推。這兩個函數都有單獨設置起或止位置的版本。例如,設置
lv_arc_set_bg_angles(arc01, 0, 270);
lv_arc_set_end_angle(arc01, 180);
可以將圓弧的角度調整為:
圓弧也像直線一樣具有特殊的樣式,下表列出了圓弧具有的樣式屬性:
屬性 | 描述 | 預設值 |
---|---|---|
arc_width |
設置圓弧寬度 | 0 |
arc_rounded |
設置圓弧端點是否為圓角 | 否 |
arc_color |
設置圓弧顏色 | 黑色 |
arc_opa |
設置圓弧透明度 | 不透明 |
arc_img_src |
設置圓弧填充圖片 | 無填充圖片 |
以上是官方文檔的介紹,但這個預設值顯然與實際不符。之所以會這樣,原因是在 lv_conf.h
大約 514 行,啟用過預設的樣式:
/*A simple, impressive and very complete theme*/
#define LV_USE_THEME_DEFAULT 1
而該樣式在初始化時,就會修改包括圓弧在內的一些樣式,因此圓弧、按鈕等控制項才預設表現為這個模樣。
圓弧可以作為一個基準讓控制項對齊。例如,可以使用
lv_arc_rotate_obj_to_angle(arc01, label, 25);
讓一個標簽旋轉對齊圓弧的把手,第三個參數為半徑的偏移量,效果為:
與其說是對齊把手,更準確的說法是對齊圓弧當前的值。例如,可以通過以下函數改變圓弧的值:
lv_arc_set_value(arc01, 20);
這樣效果就很明顯了:
圓弧預設的取值範圍是 0~100 ,也可以通過 lv_arc_set_range(obj, min, max)
函數修改這一取值範圍。除此之外,還有另一個函數 lv_arc_align_obj_to_angle(obj, obj_to_align, r_offset)
只對齊控制項而不發生旋轉。另外需要註意,應該先對齊圓弧後,再設置標簽的對齊,否則標簽會因為不是包含關係而不隨之更新位置。
總體來說,圓弧因為不是純粹的圓弧,因此它具有滑塊的各種特征,例如可以響應 LV_EVENT_VALUE_CHANGED
事件,可以使用 lv_arc_get_value(obj)
獲取值等。
首發於:http://frozencandles.fun/archives/361
參考資料/延伸閱讀
https://docs.lvgl.io/master/overview/style.html
官方文檔——樣式簡介
https://docs.lvgl.io/master/overview/style-props.html
官方文檔——所有的樣式屬性簡介