Flipper Zero 宇宙最強攻略:30 天帶你從入門到入坑 Day29 - 絶対的な優位を掌握せよ!倒数24時間、登場する圧軸必殺技!
Cover
圖片來源:https://instantiator.dev/post/flipper-zero-app-tutorial-02/
資安倫理宣導
請注意,透過 Flipper Zero 學習的資訊技術與知識,目的在於提升個人的技術能力和資安意識。我們強烈呼籲大家,絕對不要使用所學知識從事任何違法行為。您的合法使用是我們的期望,也是您自身責任的
一部分。
定義場景功能的核心步驟
當我們在開發 Flipper Zero 應用程式時,每個場景都有三個關鍵函式,這些函式主要是負責管理進入場景時的資源、處理事件以及離開場景時釋放資源,如下:
- **
*_on_enter
**:當進入場景時初始化視圖及資源。 - **
*_on_event
**:處理使用者輸入和自定義事件。 - **
*_on_exit
**:離開場景時,釋放佔用的資源。
設定主選單的回傳函式
在主選單的場景中,我們會定義一個回傳函式 test_app_menu_callback_main_menu
。這個回傳函式會接收到使用者的選擇,這個選擇值來自於 TestAppMenuSelection
。透過這個值,我們可以確認使用者選擇了哪一個選項,並將此選擇發送到場景管理器的自定義事件處理函式。這樣做的好處是將事件傳遞給場景管理器,而不是在選單回傳函式中處理事件,能夠確保每個場景都能處理自己的邏輯,提升整體的可讀性和維護性。
進入主選單場景
當我們進入主選單場景時,會調用 test_app_scene_on_enter_main_menu
函式來設定場景。這裡的工作是初始化該場景所需要的資源,並指示視圖調度器切換到對應的視圖。步驟如下:
重設選單視圖:
1
menu_reset(app->menu);
這行程式碼會重置選單,確保我們開始時的選單是乾淨的,不包含任何之前添加的項目。
添加選單項目:
每個選單項目都會用來表示一個選擇,並且會指派一個來自TestAppMenuSelection
的 ID。這個 ID 在選單回呼函式中用來確認使用者做出的選擇。例如:1
2
3
4
5
6
7menu_add_item(
app->menu,
"First popup",
NULL,
TestAppMenuSelection_One,
test_app_menu_callback_main_menu,
app);在這裡,我們為選單添加了一個名為「First popup」的選項,並指定當使用者選擇這個項目時會調用
test_app_menu_callback_main_menu
,並且將選擇項目標識(TestAppMenuSelection_One
)傳給這個回呼函式。切換到選單視圖:
最後一步是指示視圖調度器切換到選單視圖,讓使用者能夠看到並進行選擇:1
view_dispatcher_switch_to_view(app->view_dispatcher, TestAppView_Menu);
到目前為止,我們的選單場景已經成功設定好並且可以開始與使用者互動了。透過這種方式,場景管理器可以輕鬆處理每個場景的進入、退出以及事件處理,而且具有乾淨、高擴展性的應用程式架構。
處理場景中的事件
當進入選單場景時,我們會遇到不同類型的事件。這些事件主要包括自定義事件、返回事件、以及時間流逝(Tick)事件。我們通過事件處理函式來處理這些事件。
事件類型
事件類型被定義為 SceneManagerEventType
,具有三個主要值:
- SceneManagerEventTypeCustom:這是自定義事件,用來表示像是使用者的互動或輸入等事件。
- SceneManagerEventTypeBack:這個事件表示使用者正試圖返回應用程式的上一個場景。如果沒有特別處理,場景管理器會自動將使用者帶回到上一個場景。
- SceneManagerEventTypeTick:這個事件表示時間流逝,場景應該刷新並有機會更新任何隨著時間推移而改變的數據模型。
處理自定義事件
當使用者在選單中選擇某個選項時,test_app_menu_callback_main_menu
會創建 SceneManagerEventTypeCustom
類型的事件,並通過 scene_manager_handle_custom_event
發送給場景管理器。這樣的事件會被傳遞到場景管理器的 _on_event
函式,進行處理。
這些事件包含來自 TestAppEvent
的值,例如 TestAppEvent_ShowPopupOne
或 TestAppEvent_ShowPopupTwo
。處理邏輯如下:
1 | bool consumed = false; |
這段程式碼會根據不同的事件進行場景切換,例如當使用者選擇了第一個彈出視窗,則切換到 TestAppScene_FirstPopup
場景。
清理場景資源
當離開選單場景時,我們會調用 test_app_scene_on_exit_main_menu
,用來清理場景的資源:
1 | TestApp* app = context; |
雖然在進入場景時我們也重設了選單,但在離開時再次清理資源是一個比較好的習慣,這樣可以確保場景中的資源不會長期佔用記憶體。
設定彈出視窗場景
與選單場景相比,彈出視窗場景的邏輯相對簡單。每個彈出視窗的主要邏輯集中在 *_on_enter
函式中,用來初始化視窗和設置其內容。例如,以下程式碼設置了一個彈出視窗:
1 | popup_reset(app->popup); |
在這裡,我們透過 popup_set_header
和 popup_set_text
設置彈出視窗的標題和內容,最後使用 view_dispatcher_switch_to_view
切換到彈出視窗視圖。
清理彈出視窗
當離開彈出視窗場景時,我們會調用 popup_reset
來清理視窗的內容,確保不再佔用記憶體。
圖片資源管理
在程式碼中的幾個地方,我們可以看到以 I_
為前綴的 Icon 指標。這些指標是由 ufbt 在編譯過程中自動從 images/
資料夾中的資源創建出來的。
例如,在資料夾中有幾個圖像檔案:
cvc_36x36.png
:這是一個 Count von Count 的小圖像,編譯後變為I_cvc_36x46
。one.png
:10x10 尺寸的圖示,代表羅馬數字「i」,編譯後變為I_one
。two.png
:10x10 尺寸的圖示,代表羅馬數字「ii」,編譯後變為I_two
。
我們可以通過將更多的 1-bit PNG 檔案添加到該資料夾中,讓它們在編譯過程中被整合進應用程式,並在程式碼中以 Icon 資源的形式使用。
編譯與部署
首先,取得我們這邊用 instantiator.dev 在這篇部落格示範的專案示範:
1 | git clone https://github.com/instantiator/flipper-zero-tutorial-app.git |
接著,可以開始編譯應用程式:
1 | $ ufbt |
如果我們的 ufbt 工具與 Flipper 設備上的韌體版本一致,就可以將它直接部署到 Flipper 上:
1 | $ ufbt launch |
如果韌體版本與 ufbt 工具不一致,Flipper 會告訴我們。此時可以透過以下指令更新開發工具的 SDK:
1 | ufbt update --channel=[dev|rc|release] |
或者可以使用 qFlipper 來更新 Flipper 的韌體,或者使用以下指令進行 USB 刷入:
1 | ufbt flash_usb |
如果使用的是 ST-link,也可以使用以下指令:
1 | ufbt flash |
整合所有部分
通過本次的教學,我們已經介紹了如何為 Flipper Zero 應用程式初始化與啟動簡單的使用者介面。
作者提供完整的教學程式碼可以在文章最後的 References 找到,他鼓勵大家可以自由使用該專案的程式碼進行學習與修改。也建議各位去看看他的教學,並參考其他教學資源,進一步加深對 Flipper Zero 介面開發的了解。
按讚訂閱收藏小鈴噹叮叮叮
instantiator.dev 的教學我們已經完成了,明天我們會把健身海豚教練開發完成,並結束今年的鐵人賽挑戰!
各位期待明天最後一篇吧!
References
- Title: Flipper Zero 宇宙最強攻略:30 天帶你從入門到入坑 Day29 - 絶対的な優位を掌握せよ!倒数24時間、登場する圧軸必殺技!
- Author: kazma
- Created at : 2024-10-13 18:49:19
- Updated at : 2024-10-27 17:35:25
- Link: https://kazma.tw/2024/10/13/Flipper-Zero-宇宙最強攻略:30-天帶你從入門到入坑-Day29/
- License: This work is licensed under CC BY-NC-SA 4.0.