LVGL系列(四)概述 之 位置、尺寸和布局
“本文大部分內容來自LVGL官方文檔,手翻版,如有錯誤歡迎指正。”
系列文章目錄
一、LVGL系列(一)?一文了解LVGL的學習路線?輕松了解LVGL的全部?
二、LVGL系列(二)之一 LVGL必讀介紹? 為什么要學習LVGL
???????LVGL系列(二)之二 LVGL常見問題解答 整理自官方文檔
二、LVGL系列(三)LVGL仿真環境的搭建(WIN下)
? ? ? ? 2.1?VS下搭建LVGL仿真環境
? ? ? ? 2.1?如何在仿真環境下運行自己的代碼
三、LVGL系列(三) LVGL移植教程
四、LVGL系列(四)概述
? ? ? ? 4.1 對象 LVGL核心概念
? ? ? ? 4.2? 位置、尺寸和布局
五、LVGL系列(五)部件
六、LVGL系列(六)布局
文章目錄
目錄
系列文章目錄
文章目錄
一、概覽??
1.1?單位(Units)
1.2 盒子模型 Boxing model
1.3 Important notes
1.4 延遲坐標推算 Postponed coordinate calculation
1.5 移除樣式 Removing styles
二、 位置(Position)
2.1 簡單方式?Simple way?
2.2 對齊(Align)
三 、 尺寸(Size)
3.1 簡單方法(Simple way)
四、通過樣式實現
五、 轉換?Translation
六、變換Transformation
6.1?最大最小尺寸(Min and Max size)
七、 布局Layout
7.1 概覽(Overview)
7.2 標志 (Flags)
7.3 Adding new layouts(添加新的布局)
一、概覽??
????????跟LVGL其他的部分相似,坐標設定的概念靈感來自于CSS。并不是完全的按照其標準實現,而是實現了一小部分功能,會有一些小調整。簡而言之,這意味著:
- 坐標(size, position, layouts, etc)的設定是通過styles實現的。
- 支持最小寬度、最大寬度、最低高度、最大高度。
- 具有像素、百分比和“內容”單位。
- x=0; y=0 的坐標意味著在父類的左上角加上左上填充加上邊框寬度。
- 高度/寬度是指全尺寸,內容區域隨著填充的和邊框的寬度增加而減小。
- 支持flexbox和grid布局的子集。
1.1?單位(Units)
- 像素:簡單的說在像素中的一個位置,一個簡單的整數可代替像素的位置。例如:lv_obj_set_x(btn,? 10)。
- 百分比:對象或者它父類的百分比(依賴于父類的大小)。函數lv_pct(value) 能向百分比傳遞一個值。例如:lv_obj_set_width(btn,? lv_pct(50))??
- LV_SIZE_CONTENT: 用于設置一個對象和它子對象高度和寬度的特殊值。它類似于CSS里的自動設置。例如:lv_obj_set_width(btn,? LV_SIZE_CONTENT).
1.2 盒子模型 Boxing model
????????LVGL 遵循 CSS的 border-box 模型. 一個對象的“box”由以下部分組成:An object's "box" is built from the following parts:
- 邊界框(bounding box): 元素的高度和寬度。the width/height of the elements.
- 邊界寬度(border width):邊界的寬度,邊界框的寬度。the width of the border.
- 填充(padding):在一個對象和它子對象之間的空間。: space between the sides of the object and its children.
- 內容(content): 內容區域的大小是除去邊界框、邊界寬度、填充區域剩下的區域。
邊界在邊界框里面繪制,在邊界內部,LVGL保持填充區域以放置子對象。輪廓在邊界框外面繪制。
1.3 Important notes
本節介紹LVGL行為可能意外的特殊情況。
1.4 延遲坐標推算 Postponed coordinate calculation
????????LVGL不會立即重新計算所有坐標的變化。這樣做是為了提升性能。相反,有些對象被標記為"dirty"并且在重新繪制屏幕之前,LVGL會檢查是否有一些"dirty"。如果是,LVGL就會刷新他們的位置、尺寸和布局。
????????換句話說, 如果你需要獲取一個對象的坐標而且它的坐標剛剛發生改變,需要強制LVGL重新計算坐標。可以調用lv_obj_update_layout(obj)來實現。
??? 尺寸和位置可能會依賴與父類或者布局。因此lv_obj_update_layout(obj).會重新計算在屏幕上的所有對象的坐標。
1.5 移除樣式 Removing styles
????????正如Using style部分所述:坐標同樣可以通過style參數的方式進行設置。更準確地說,在后臺,每個與樣式坐標相關的屬性都存儲為樣式屬性。如果你使用了lv_obj_set_x(obj,? 20),LVGL將在對象的本地樣式中保存x=20。這是一個內部的工作機制,跟你使用的LVGL沒有太大關系。但是,有一種情況你需要知道。如果一個對象的樣式被移除,通過:
1. lv_obj_remove_style_all (obj)或者
1. lv_obj_remove_style(obj, NULL , LV_PART_MAIN);????????在此之前設置的坐標也會被移除。
例如:
1. /*The size of obj1 will be set back to the default in the end*/ 2. lv_obj_set_size(obj1, 200, 100); /*Now obj1 has 200;100 size*/ 3. lv_obj_remove_style_all(obj1); /*It removes the set sizes*/ 4. /*obj2 will have 200;100 size in the end */ 5. lv_obj_remove_style_all(obj2); 6. lv_obj_set_size(obj2, 200, 100);二、 位置(Position)
2.1 簡單方式?Simple way?
????????簡單的給一個對象設置x和y坐標可以通過下列方法:
1. lv_obj_set_x(obj, 10); 2. lv_obj_set_y(obj, 20); 3. lv_obj_set_pos(obj, 10, 20); //Or in one function????????默認情況下,x和y坐標從父級內容區域的左上角測量。例如:如果父對象在每個邊上都有5個像素的填充區域,上面的代碼會把對象放在(15,25),這是因為內容區域是在填充之后開始的。
????????如果根據父對象的內容區域的大小計算百分比的值:
1. lv_obj_set_x(btn, lv_pct(10)); //x = 10 % of parant content area width2.2 對齊(Align)
????????在某些情況下,可以很方便的修改位置標的默認原點。如果原點被更改,例如:對于左下角,(0,0)意味著:與右下角對齊。改變原點可以通過:
1. lv_obj_set_align(obj, align);????????改變排列并設置新的坐標:
1. lv_obj_align(obj, align, x, y);????????下列的一些排列位置可以使用:
- LV_ALIGN_TOP_LEFT
- LV_ALIGN_TOP_MID
- LV_ALIGN_TOP_RIGHT
- LV_ALIGN_BOTTOM_LEFT
- LV_ALIGN_BOTTOM_MID
- LV_ALIGN_BOTTOM_RIGHT
- LV_ALIGN_LEFT_MID
- LV_ALIGN_RIGHT_MID
- LV_ALIGN_CENTER
????????將父對象和子對象對齊是十分常見的,因此對于這個功能有一個專門對應的方法:
1. lv_obj_center(obj); 2. 3. //Has the same effect 4. lv_obj_align(obj, LV_ALIGN_CENTER, 0, 0);????????如果父對象的的尺寸發生了變化,子對象的對齊設置和位置會自動重新的排列。
上面介紹的函數將對象與它的父類對齊。然而,他也有可能與一個任意的對象對齊。
1. lv_obj_align_to(obj_to_align, reference_obj, align, x, y);除了上面的一些對齊方式之外,下面的一些選項可以用來將對象與參考對象的外邊對齊:
- LV_ALIGN_OUT_TOP_LEFT
- LV_ALIGN_OUT_TOP_MID
- LV_ALIGN_OUT_TOP_RIGHT
- LV_ALIGN_OUT_BOTTOM_LEFT
- LV_ALIGN_OUT_BOTTOM_MID
- LV_ALIGN_OUT_BOTTOM_RIGHT
- LV_ALIGN_OUT_LEFT_TOP
- LV_ALIGN_OUT_LEFT_MID
- LV_ALIGN_OUT_LEFT_BOTTOM
- LV_ALIGN_OUT_RIGHT_TOP
- LV_ALIGN_OUT_RIGHT_MID
- LV_ALIGN_OUT_RIGHT_BOTTOM
????????例如:要對齊按鈕上方的標簽并且使標簽水平居中對齊:
1. lv_obj_align_to(label, btn, LV_ALIGN_OUT_TOP_MID, 0, -10);請注意:不像lv_obj_align()一樣,lv_obj_align_to()并不能在它的坐標或者參考對象的坐標發生改變后重新對齊。
三 、 尺寸(Size)
3.1 簡單方法(Simple way)
????????一個對象的寬度和高度也可以輕松設置,方法如下:
1. lv_obj_set_width(obj, 200); 2. lv_obj_set_height(obj, 100); 3. lv_obj_set_size(obj, 200, 100); //Or in one function????????百分比值是基于父對象的內容區域大小計算的。例如:要將對象的高度設置成屏幕的高度
1. lv_obj_set_height(obj, lv_pct(100))????????尺寸設置支持單值:LV_SIZE_CONTENT 。這意味著對象在各自的方向上的尺寸大小將設置為它子類的大小。請注意:只考慮右下的子類,而左上的將會保持裁剪。這種限制讓對象的行為更加可預測。
???具有LV_OBJ_FLAG_HIDDEN or LV_OBJ_FLAG_FLOATING屬性的對象會被LV_SIZE_CONTENT算法忽略。
????????上面的函數不光可以設置對象邊界的尺寸,而且也可以設置內容區域的尺寸。這意味著對象的邊界在填充后大于設置的尺寸。
1. lv_obj_set_content_width(obj, 50); //The actual width: padding left + 50 + padding right 2. lv_obj_set_content_height(obj, 30); //The actual width: padding top + 30 + padding bottom可通過以下功能獲取邊界框和內容區域的大小:
1. lv_coord_t w = lv_obj_get_width(obj); 2. lv_coord_t h = lv_obj_get_height(obj); 3. lv_coord_t content_w = lv_obj_get_content_width(obj); 4. lv_coord_t content_h = lv_obj_get_content_height(obj);四、通過樣式實現
????????位置、尺寸、對齊方式等屬性是樣式屬性。為了簡單起見,上面所描述的簡單函數隱藏了與樣式相關的代碼,并且在本地樣式中設置了對象的位置、大小、和對齊方式幾個屬性。
????????但是,使用樣式來設置坐標有非常多的優點:
- 可以一起輕松設置多個對象的寬度/高度等屬性。例如:設置所有的滑塊100×10像素大小。
- 可以在一個位置修改屬性值。
- 這些值可以被其他樣式覆蓋。例如在默認狀態下style_btn 設置對象為100×50,但是style_full_width 函數能夠覆蓋對象的寬度特性。
- 對象可以在不同的狀態下具有不同的位置和大小。例如:在默認狀態下為100px 而在LV_STATE_PRESSED 下為120px。
- 樣式傳遞可以使坐標變化平滑。
以下時使用樣式來設置對象大小的例子:
1. static lv_style_t style; 2. lv_style_init(&style); 3. lv_style_set_width(&style, 100); 4. lv_obj_t * btn = lv_btn_create(lv_scr_act()); 5. lv_obj_add_style(btn, &style, LV_PART_MAIN);????????正如你即將在下面看到的一樣,還有一些其他關于設置位置和尺寸的強大功能。然而為了保持LVGl的API的簡潔性,只有最常見的坐標設置具有最簡版本,對于更復雜的屬性設置通過樣式來實現。
五、 轉換?Translation
????????比方說:現在有相鄰的3個按鈕,它們的位置設置像上面說的一樣。現在,你想在按鈕被按下的時,讓按鈕向上一點。
????????實現這個設置的一個方式是給按壓狀態設置一個新的Y坐標:
1. static lv_style_t style_normal; 2. lv_style_init(&style_normal); 3. lv_style_set_y(&style_normal, 100); 4. static lv_style_t style_pressed; 5. lv_style_init(&style_pressed); 6. lv_style_set_y(&style_pressed, 80); 7. lv_obj_add_style(btn1, &style_normal, LV_STATE_DEFAULT); 8. lv_obj_add_style(btn1, &style_pressed, LV_STATE_PRESSED); 9. lv_obj_add_style(btn2, &style_normal, LV_STATE_DEFAULT); 10. lv_obj_add_style(btn2, &style_pressed, LV_STATE_PRESSED); 11. lv_obj_add_style(btn3, &style_normal, LV_STATE_DEFAULT); 12. lv_obj_add_style(btn3, &style_pressed, LV_STATE_PRESSED);?????????可以通過上面的的方式實現這個需求,但是,由于這是硬編碼實現的,看起來不夠絲滑。如果按鈕不在y=100,style_pressed不會按照預期的那樣工作。為了解決這個問題可以使用Translation來實現:
1. static lv_style_t style_normal; 2. lv_style_init(&style_normal); 3. lv_style_set_y(&style_normal, 100); 4. static lv_style_t style_pressed; 5. lv_style_init(&style_pressed); 6. lv_style_set_translate_y(&style_pressed, -20); 7. lv_obj_add_style(btn1, &style_normal, LV_STATE_DEFAULT); 8. lv_obj_add_style(btn1, &style_pressed, LV_STATE_PRESSED); 9. lv_obj_add_style(btn2, &style_normal, LV_STATE_DEFAULT); 10. lv_obj_add_style(btn2, &style_pressed, LV_STATE_PRESSED); 11. lv_obj_add_style(btn3, &style_normal, LV_STATE_DEFAULT); 12. lv_obj_add_style(btn3, &style_pressed, LV_STATE_PRESSED);????????通過上面的操作變換(Translation)被應用于對象的當前位置。
????????百分比值也用于(Translation)。對象的大小與百分比有關(不會作用于父類)。比如:lv_pct(50)可以使對象移動到它的寬或高一半的距離。
在布局計算之后轉換(translation)才會應用。因此即使已經布局的對象的位置一樣可以被轉換。
轉換(translation)實際上上是移動了對象(這本文中translation叫平移更加合適)。這就意味著它可以使滾動條和LV_SIZE_CONTENT對象對位置改變做出反應。
六、變換Transformation
????????與位置屬性相似,尺寸屬性也可以相對于當前尺寸大小改變。變換后的寬度和高度將會添加到對象的兩邊。這意味著在寬度10個像素的變換實際上使對象擴展到2×10個像素的寬度。
????????不像位置變換一樣,尺寸變換不會讓對象真正的變大。換句話說,滾動條、布局、LV_SIZE_CONTENT不會考慮轉換大小。因此如果僅僅是一個視覺效果使用尺寸變化更合適。
????????下面的代碼使一個按鈕在按下時變大:
1. static lv_style_t style_pressed; lv_style_init(&style_pressed); 2. lv_style_set_transform_width(&style_pressed, 10); 3. lv_style_set_transform_height(&style_pressed, 10); 4. 5. lv_obj_add_style(btn, &style_pressed, LV_STATE_PRESSED);????????與位置相似,大小也可以根據當前大小進行更改。轉換后的寬度和高度被添加到對象的兩邊。這意味著10像素的轉換寬度使對象寬2x10像素。
????????與位置平移不同,這種大小的轉換并不會讓對象真正的變大。換句話說,滑塊、布局、LV_SIZE_CONTENT將不考慮轉換后的大小。因此這樣的尺寸變化只是一個視覺效果。
下面的代碼可以實現當按鈕被按下時變大的效果:
1. static lv_style_t style_pressed; lv_style_init(&style_pressed); 2. lv_style_set_transform_width(&style_pressed, 10); 3. lv_style_set_transform_height(&style_pressed, 10); 4. 5. lv_obj_add_style(btn, &style_pressed, LV_STATE_PRESSED);6.1?最大最小尺寸(Min and Max size)
????????類似于CSS,LVGL也支持min-width, max-width, min-height 和 max-height.他們可以限制對象尺寸的范圍。如果這些值由百分比或者LV_SIZE_CONTENT設置,這些限制非常有效。
1. static lv_style_t style_max_height; 2. lv_style_init(&style_max_height); 3. lv_style_set_y(&style_max_height, 200); 4. lv_obj_set_height(obj, lv_pct(100)); 5. lv_obj_add_style(obj, &style_max_height, LV_STATE_DEFAULT); //Limit the height to 200 px還可以使用相對于父類內容區域大小的百分比值:
1. static lv_style_t style_max_height; 2. lv_style_init(&style_max_height); 3. lv_style_set_y(&style_max_height, lv_pct(50)); 4. lv_obj_set_height(obj, lv_pct(100)); 5. lv_obj_add_style(obj, &style_max_height, LV_STATE_DEFAULT); //Limit the height to?half parent heigh七、 布局Layout
7.1 概覽(Overview)
????????布局能夠更新一個對象的子類的位置和尺寸大小。他們能夠使子類自動的按照一行或者一列的方式排布,或者更加復雜的方式。
????????布局設置的位置和大小將覆蓋正常情況下x,y,高度、寬度的設置。
????????每個布局只有一個相同的功能:lv_obj_set_layout(obj,? <LAYOUT_NAME>)設置對象上的布局。有關父級類和子類的進一步設置,請參閱給定布局的文檔。
7.2內置布局Built-in layout
LVGL具有兩個非常強大的布局:
- Flexbox
- Grid
兩者都深受同名 CSS 布局的啟發。
7.2 標志 (Flags)
可以在對象上使用一些標志可以用來影響布局時對象的行為:
LV_OBJ_FLAG_HIDDEN :在布局運算中忽略隱藏對象。
- LV_OBJ_FLAG_IGNORE_LAYOUT 布局只會忽略該對象,它的坐標可以像往常一樣被設置。
- LV_OBJ_FLAG_FLOATING??????????? 跟LV_OBJ_FLAG_IGNORE_LAYOUT相似,但是使用LV_OBJ_FLAG_FLOATING的對象 將會從LV_SIZE_CONTENT 計算中被忽略。
這些標志可以添加或者刪除通過方法: lv_obj_add/clear_flag(obj,? FLAG);
7.3 Adding new layouts(添加新的布局)
LVGL可以通過如下自定義布局自由的擴展:
1. uint32_t MY_LAYOUT; 2. ... 3. MY_LAYOUT = lv_layout_register(my_layout_update, &user_data); 4. ... 5. void my_layout_update(lv_obj_t * obj, void * user_data) 6. { 7. /*Will be called automatically if required to reposition/resize the children of "obj" */ 8. }還可以添加自定義風格屬性,這些屬性可以在更新回調函數中獲取,例如:
1. uint32_t MY_PROP; 2. ... 3. LV_STYLE_MY_PROP = lv_style_register_prop(); 4. ... 5. static inline void lv_style_set_my_prop(lv_style_t * style, uint32_t value) 6. { 7. lv_style_value_t v = { 8. .num = (int32_t)value 9. }; 10. lv_style_set_prop(style, LV_STYLE_MY_PROP, v); 11. }總結
以上是生活随笔為你收集整理的LVGL系列(四)概述 之 位置、尺寸和布局的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java tessdata训练_Tess
- 下一篇: 张沈鹏诗歌集