前一篇文章通過官方給的基於Linux FrameBuffer的LittlevGL例程學習了LittlevGL的移植步驟。本文將繼續學習基於Linux FrameBuffer的Demo例程。
先上帶註釋的demo_create函數代碼:
void demo_create(void)
{
lv_coord_t hres = lv_disp_get_hor_res(NULL); //獲取顯示器的分辨率信息
lv_coord_t vres = lv_disp_get_ver_res(NULL);
#if LV_DEMO_WALLPAPER
lv_obj_t * wp = lv_img_create(lv_disp_get_scr_act(NULL), NULL); //創建一個基於當前界面的圖片框控件
lv_img_set_src(wp, &img_bubble_pattern); //設置圖片框的圖像數據源
lv_obj_set_width(wp, hres * 4); //設置圖片框的寬度
lv_obj_set_protect(wp, LV_PROTECT_POS); //Prevent automatic positioning (e.g. in lv_cont layout)
#endif
static lv_style_t style_tv_btn_bg; //創建一個樣式對象
lv_style_copy(&style_tv_btn_bg, &lv_style_plain); //使用lv_style_plain爲模板
style_tv_btn_bg.body.main_color = lv_color_hex(0x487fb7);
style_tv_btn_bg.body.grad_color = lv_color_hex(0x487fb7);
style_tv_btn_bg.body.padding.top = 0;
style_tv_btn_bg.body.padding.bottom = 0;
static lv_style_t style_tv_btn_rel; //創建一個按鍵鬆開時的樣式對象
lv_style_copy(&style_tv_btn_rel, &lv_style_btn_rel);
style_tv_btn_rel.body.opa = LV_OPA_TRANSP;
style_tv_btn_rel.body.border.width = 0;
static lv_style_t style_tv_btn_pr; //創建一個按鍵按下時的樣式對象
lv_style_copy(&style_tv_btn_pr, &lv_style_btn_pr);
style_tv_btn_pr.body.radius = 0;
style_tv_btn_pr.body.opa = LV_OPA_50;
style_tv_btn_pr.body.main_color = LV_COLOR_WHITE;
style_tv_btn_pr.body.grad_color = LV_COLOR_WHITE;
style_tv_btn_pr.body.border.width = 0;
style_tv_btn_pr.text.color = LV_COLOR_GRAY;
lv_obj_t * tv = lv_tabview_create(lv_disp_get_scr_act(NULL), NULL); //創建一個tabview控件
lv_obj_set_size(tv, hres, vres); //設置tabview控件的大小佔滿整個顯示器
#if LV_DEMO_WALLPAPER
lv_obj_set_parent(wp, ((lv_tabview_ext_t *) tv->ext_attr)->content); //設置圖片框的父控件
lv_obj_set_pos(wp, 0, -5); //設置圖片框在父控件上的顯示位置
#endif
lv_obj_t * tab1 = lv_tabview_add_tab(tv, "Write"); //爲tabview控件添加視圖窗口
lv_obj_t * tab2 = lv_tabview_add_tab(tv, "List");
lv_obj_t * tab3 = lv_tabview_add_tab(tv, "Chart");
#if LV_DEMO_WALLPAPER == 0
/*Blue bg instead of wallpaper*/
lv_tabview_set_style(tv, LV_TABVIEW_STYLE_BG, &style_tv_btn_bg);
#endif
lv_tabview_set_style(tv, LV_TABVIEW_STYLE_BTN_BG, &style_tv_btn_bg); //設置tabview的樣式
lv_tabview_set_style(tv, LV_TABVIEW_STYLE_INDIC, &lv_style_plain);
lv_tabview_set_style(tv, LV_TABVIEW_STYLE_BTN_REL, &style_tv_btn_rel);
lv_tabview_set_style(tv, LV_TABVIEW_STYLE_BTN_PR, &style_tv_btn_pr);
lv_tabview_set_style(tv, LV_TABVIEW_STYLE_BTN_TGL_REL, &style_tv_btn_rel);
lv_tabview_set_style(tv, LV_TABVIEW_STYLE_BTN_TGL_PR, &style_tv_btn_pr);
write_create(tab1); //爲tabview單獨創建3個視圖
list_create(tab2);
chart_create(tab3);
#if LV_DEMO_SLIDE_SHOW
lv_task_create(tab_switcher, 3000, LV_TASK_PRIO_MID, tv); //創建一個週期調用的“任務”用於實現自動翻頁功能
#endif
}
再看看其中的write_create函數的實現:
static void write_create(lv_obj_t * parent)
{
lv_page_set_style(parent, LV_PAGE_STYLE_BG, &lv_style_transp_fit); //設置頁面樣式
lv_page_set_style(parent, LV_PAGE_STYLE_SCRL, &lv_style_transp_fit);
lv_page_set_sb_mode(parent, LV_SB_MODE_OFF); //不顯示scrollbars
static lv_style_t style_ta; //創建一個文本框的樣式對象
lv_style_copy(&style_ta, &lv_style_pretty);
style_ta.body.opa = LV_OPA_30;
style_ta.body.radius = 0;
style_ta.text.color = lv_color_hex3(0x222);
ta = lv_ta_create(parent, NULL); //創建有一個文本框控件對象
lv_obj_set_size(ta, lv_page_get_scrl_width(parent), lv_obj_get_height(parent) / 2); //設置文本框的大小
lv_ta_set_style(ta, LV_TA_STYLE_BG, &style_ta); //設置文本框的樣式
lv_ta_set_text(ta, ""); //設置文本框中的內容爲空
lv_obj_set_event_cb(ta, text_area_event_handler); //設置文本框的事件回調函數
lv_style_copy(&style_kb, &lv_style_plain); //設置鍵盤樣式
lv_ta_set_text_sel(ta, true); //設置文本框爲可選擇模式
style_kb.body.opa = LV_OPA_70; //設置鍵盤樣式
style_kb.body.main_color = lv_color_hex3(0x333);
style_kb.body.grad_color = lv_color_hex3(0x333);
style_kb.body.padding.left = 0;
style_kb.body.padding.right = 0;
style_kb.body.padding.top = 0;
style_kb.body.padding.bottom = 0;
style_kb.body.padding.inner = 0;
lv_style_copy(&style_kb_rel, &lv_style_plain); //設置鍵盤松開狀態時樣式
style_kb_rel.body.opa = LV_OPA_TRANSP;
style_kb_rel.body.radius = 0;
style_kb_rel.body.border.width = 1;
style_kb_rel.body.border.color = LV_COLOR_SILVER;
style_kb_rel.body.border.opa = LV_OPA_50;
style_kb_rel.body.main_color = lv_color_hex3(0x333); /*Recommended if LV_VDB_SIZE == 0 and bpp > 1 fonts are used*/
style_kb_rel.body.grad_color = lv_color_hex3(0x333);
style_kb_rel.text.color = LV_COLOR_WHITE;
lv_style_copy(&style_kb_pr, &lv_style_plain); //設置鍵盤按下狀態時樣式
style_kb_pr.body.radius = 0;
style_kb_pr.body.opa = LV_OPA_50;
style_kb_pr.body.main_color = LV_COLOR_WHITE;
style_kb_pr.body.grad_color = LV_COLOR_WHITE;
style_kb_pr.body.border.width = 1;
style_kb_pr.body.border.color = LV_COLOR_SILVER;
}
發現這個函數裏面並沒有創建鍵盤控件,而是隻創建了一個文本框的控件,但是爲文本框設置了一個事件回調函數:
static void text_area_event_handler(lv_obj_t * text_area, lv_event_t event)
{
(void) text_area; /*Unused*/
/*Text area is on the scrollable part of the page but we need the page itself*/
lv_obj_t * parent = lv_obj_get_parent(lv_obj_get_parent(ta)); //獲取page指針
if(event == LV_EVENT_CLICKED) {
if(kb == NULL) {
kb = lv_kb_create(parent, NULL); //如果鍵盤還沒有被創建的話,創建一個鍵盤控件
lv_obj_set_size(kb, lv_obj_get_width_fit(parent), lv_obj_get_height_fit(parent) / 2); //設置鍵盤控件的size
lv_obj_align(kb, ta, LV_ALIGN_OUT_BOTTOM_MID, 0, 0); //設置文本框和鍵盤對齊方式
lv_kb_set_ta(kb, ta); //制定鍵盤的輸出到文本框中去
lv_kb_set_style(kb, LV_KB_STYLE_BG, &style_kb); //設置鍵盤的樣式
lv_kb_set_style(kb, LV_KB_STYLE_BTN_REL, &style_kb_rel);
lv_kb_set_style(kb, LV_KB_STYLE_BTN_PR, &style_kb_pr);
lv_obj_set_event_cb(kb, keyboard_event_cb); //設置鍵盤的事件回調函數
#if LV_USE_ANIMATION
lv_anim_t a; //如果定義了使用動畫的話創建一個動畫對象,用於動態顯示鍵盤(裝逼)
a.var = kb;
a.start = LV_VER_RES;
a.end = lv_obj_get_y(kb);
a.exec_cb = (lv_anim_exec_xcb_t)lv_obj_set_y;
a.path_cb = lv_anim_path_linear;
a.ready_cb = NULL;
a.act_time = 0;
a.time = 300;
a.playback = 0;
a.playback_pause = 0;
a.repeat = 0;
a.repeat_pause = 0;
lv_anim_create(&a);
#endif
}
}
}
可以看出來鍵盤的創建實在文本框的事件回調函數中實現的,也就是說點擊一下文本框就會彈出鍵盤來,如果定義了LV_USE_ANIMATION = 1的話,鍵盤的出現會帶一個5毛錢的特效(安卓系統既視感)。還注意到鍵盤控件也有一個事件回調函數keyboard_event_cb:
static void keyboard_event_cb(lv_obj_t * keyboard, lv_event_t event)
{
(void) keyboard; /*Unused*/
lv_kb_def_event_cb(kb, event); //鍵盤的 默認/通用 事件處理回調函數,參考函數說明
if(event == LV_EVENT_APPLY || event == LV_EVENT_CANCEL) {
#if LV_USE_ANIMATION
lv_anim_t a;
a.var = kb;
a.start = lv_obj_get_y(kb);
a.end = LV_VER_RES;
a.exec_cb = (lv_anim_exec_xcb_t)lv_obj_set_y;
a.path_cb = lv_anim_path_linear;
a.ready_cb = kb_hide_anim_end;
a.act_time = 0;
a.time = 300;
a.playback = 0;
a.playback_pause = 0;
a.repeat = 0;
a.repeat_pause = 0;
lv_anim_create(&a);
#else
lv_obj_del(kb);
kb = NULL;
#endif
}
}
到這裏就完成了一個視圖的創建了,剩下的list_create和chart_create都是相似的,感興趣的朋友可以自己研究一下。這裏抱着學習的態度研究了例程,後面會使用模擬器進行自己的應用設計。
由於使用Linux的FrameBuffer只實現了顯示器的驅動移植,沒有移植輸入設備的驅動移動,所以Demo沒法進行交互,但是Demo的效果可以查看:https://littlevgl.com/demo-basic,這是一個網頁模擬器,效果還不錯。