国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

WouoUI-PageVersion 一個用于快速構(gòu)建具有絲滑OLED_UI動畫的項目

這篇具有很好參考價值的文章主要介紹了WouoUI-PageVersion 一個用于快速構(gòu)建具有絲滑OLED_UI動畫的項目。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

WouoUI-PageVersion

寫在前面

簡介&致謝

  • Air001的TestUI例子的b站的演示視頻

  • Air001的LittleClock例子的b站演示視頻: https://www.bilibili.com/video/BV1J6421g7H1/

  • Stm32的TestUI例子的b站演示視頻: https://www.bilibili.com/video/BV1mS421P7CZ/

    所有演示的工程文件都使用zip壓縮包上傳在對應(yīng)的文件夾下。

    本項目的Github鏈接為:https://github.com/Sheep118/WouoUI-PageVersion

這是一個改動自WouoUI(1.2版本)的純C語言,無依賴庫,只適用于128*64OLED的代碼框架,將WouoUI抽象出一部分統(tǒng)一的接口,以方便快速構(gòu)建一個具有類似WouoUI風格的OLEDUI。

在此十分感謝WouoUI作者開源WouoUI的源碼????,這是WouoUI的Github鏈接和作者的b站鏈接。

(推薦大家可以去閱讀下WouoUI的源代碼(Arduino),寫得非常好,邏輯相當清晰)。

想法由來和一些啰嗦

WouoUIPage版的想法是源自我自己想將使用WouoUI用到自己設(shè)置的一個很簡單時鐘上,但由于使用的芯片是合宙的Air001(為啥用這個芯片,因為手頭這個芯片剩的比較多??),不過,因為這個芯片只有4k的RAM和32k的Flash,移植U8g2后再移植WouoUI,芯片的Flash和RAM基本上就用完了,很難再寫應(yīng)用層的代碼,因此,我自己根據(jù)128*64的OLED的需要,參考很多資料自己寫了圖形層的繪制驅(qū)動(oled_g.c和oled_g.h)。同時,把WouoUI用尚不成熟面向?qū)ο蟮乃枷胗肅語言重寫了一遍并抽象出接口(oled_ui.c和oled_ui.h),根據(jù)自己的需要,還加入了滾動的時鐘的頁面,至此,WouoUI Page版就此成型。

至于為何取名叫WouoUI Page版,一方面是由于這個項目本來就是從原來WouoUI改動而來,另一方面,抽象出來的接口都以一個頁面(Page)為最小單位,所以取名叫WouoUI Page版??。

WouoUIPage版和WouoUI不同

因為我參考原作者的WouoUI是1.2版本的,因此,作者后來更新的一些新的動畫沒有加進來(之后看是否有空,再決定是否加進來了??, 到時候估計也需要換個芯片了,air001Falsh太小了,而且提供的例程也只支持keil內(nèi)的O0優(yōu)化)。

WouoUI Page版
依賴庫 依賴U8g2庫,適用性廣,拓展性強 ;但消耗的RAM和FLASH可能會較多(特別是對于使用C語言開發(fā)而不是使用Arduino開發(fā)的情況) 自己寫的圖形層驅(qū)動文件,功能比較少只提供必須用到的,純C語言編寫,對內(nèi)存有限,使用C開發(fā)單片機來說比較合適;但由于沒有使用U8g2庫,適用性、拓展性差。(后面看看自己有沒有時間將上面的這部分抽象移植到U8g2圖形庫上)
接口 原作者的所有代碼都在一個.ino文件中完成,方便查看源碼; 但需要讀懂一部分源碼才能二次開發(fā) 統(tǒng)一了一部分接口,并做了抽象,二次開發(fā)時只需要按接口文檔來使用提供的接口函數(shù)
適用性 原作者開發(fā)了適應(yīng)多個屏幕尺寸的版本??(這點我自己覺得可能很難做到) 因為項目的需要,Page版只有128*64這一個尺寸適配,我也沒有做其他屏幕的開發(fā)。

移植說明

WouoUIPage版源代碼非常簡單,只有oled_g.c , oled_ui.c 兩個.c文件和 oled_g.h , oled_ui.h ,oled_conf.h , oledfont.h 和 oled_port.h 5個.h文件組成。

本項目的文件說明

|---Csource
	|---src  (這個文件夾是WouoUIPage最主要的源代碼文件,移植時主要用這里面的幾個文件)
	|---example  (這個是使用WouoUIPage所提供的接口構(gòu)建的一些應(yīng)用的例子,只有對應(yīng).c.h文件)
|---ProjectExamples  (這個文件夾內(nèi)放著使用WouoUIPage的工程的參考,按主控的類型劃分,為移植時提供一些參考)
|---Image (存放一些展示用的圖片)

移植大致流程

移植時,可以參考ProjectExamples文件夾下的工程(工程有目前有使用Air001和STM32的例子)

  1. 將上述說明的7個文件包含在工程中。

  2. 根據(jù)自己128*64的OLED屏和自己使用的MCU完成一個oled_port.c文件,這個文件包含提供的oled_port.h文件,并實現(xiàn)oled_port.h中聲明的兩個函數(shù) OLED_Init OLED_SendBuff

    一般這兩個函數(shù)OLED廠商都會提供對應(yīng)的代碼,或者根據(jù)廠商的代碼簡單修改也能得到。

    (這里建議先測試廠商的代碼,確保能夠驅(qū)動OLED屏,再移植WouoUIPage)

    void OLED_Init(void);

    這個函數(shù)需要實現(xiàn)OLED的底層初始化,如IIC接口/SPI接口 和 D/C 、RST 等IO口的初始化

    void OLED_SendBuff(uint8_t buff[8][128]);

    這個函數(shù)需要實現(xiàn)128*64的OLED顯存的刷新,即將傳入的數(shù)組全部寫到OLED顯存中

    (這里建議硬件上使用SPI或者至少是硬件IIC,軟件IIC刷新速率可能太慢,對動畫效果有影響)

    OLED_LOG 這個宏是用于打印一些錯誤提示信息的,但因為現(xiàn)在暫時還沒有使用到??,不用理會。

OK ,到這里的話,就算移植結(jié)束了(感覺說是復(fù)制更為合適,因為基本沒有改啥??),可以開始使用WouoUIPage提供的接口了。

整體框架說明和配置文件oled_conf.h

整體框架說明

如下圖所示,WouoUIPage版以6種頁面為基礎(chǔ)來構(gòu)建UI,內(nèi)部有一個消息隊列用于接收外界的消息,每個頁面都有一個回調(diào)函數(shù),會將當前頁面選中項的信息傳入,對應(yīng)操作便可以寫在回調(diào)函中。

WouoUI-PageVersion 一個用于快速構(gòu)建具有絲滑OLED_UI動畫的項目,WouoUI Page版,ui,單片機,stm32,oled,絲滑動畫

配置文件oled_conf.h

配置文件中主要有幾個宏,具體的宏的解釋可以直接看代碼注釋。

#define UI_CONWIN_ENABLE            1  //是否使能 以"$ " 為開頭的選項使用確認彈窗
#define UI_MAX_PAGE_NUM             32 //頁面的最大數(shù)量,這個數(shù)字需要大于所有頁面的page_id
#define UI_INPUT_MSG_QUNEE_SIZE     4  //ui內(nèi)部消息對列的大小(至少需要是2)

//頁面類型使能宏,使用對應(yīng)的頁面類型,則需要開啟該宏,將宏置為1,默認都開啟
#define PAGE_WAVE_ENABLE        1
#define PAGE_RADIO_ENABLE       1
#define PAGE_RADERPIC_ENABLE    1
#define PAGE_DIGITAL_ENABLE     1

接口函數(shù)的使用

這個部分會說明一部分構(gòu)建UI可能用到的結(jié)構(gòu)體類型(類)和一些函數(shù)。構(gòu)建的時候也參考CSource/example的例子(其實只有兩個??)。

類(結(jié)構(gòu)體類型)

一共有6種頁面類型 TitlePage 、ListPage 、WavePage 、 RadioPageRaderPicPageDigitalPage ,還有3個比較重要的類 InputMsg 、 OptionCallBackFunc 。其他的一些枚舉類型一些只有個別函數(shù)才會用到的結(jié)構(gòu)體就不一一說明了,根據(jù)函數(shù)說明填入對應(yīng)類型即可。

  • InputMsg : 輸入信息枚舉類型,作為void OLED_MsgQueSend(InputMsg msg); 的參數(shù)類型,用于給UI輸入一個外界動作的消息,枚舉的消息共有以下幾種:

    typedef enum 
    {
      msg_none = 0x00, //none表示沒有操作
      msg_up,      //上,或者last消息,表上一個
      msg_down,    //下,或者next消息,表下一個
      msg_return,  //返回消息,表示返回,從一個頁面退出
      msg_click,   //點擊消息,表確認,確認某一選項,回調(diào)用一次回調(diào)
      msg_home,    //home消息,表回主界面(尚未設(shè)計,目前還沒有設(shè)計對應(yīng)的功能,默認以page_id為0的頁面為主頁面)
    } InputMsg; //輸入消息類型,UI設(shè)計只供輸入5種消息
    
  • Option :選項類,其結(jié)構(gòu)體成員如下:

    typedef struct 
    {
      uint8_t order;  //該選項在列表/磁貼中的排序(0-255)
      int16_t  item_max; //列表項對應(yīng)變量可取的最大值(若是單選/多選框,該值無意義,可為0)
      int16_t  item_min; //列表項對應(yīng)變量可取的最小值(若是單選/多選框,該值無意義,可為0)
      int16_t  step;//列表項對應(yīng)變量的步長變化,只對數(shù)值彈窗有效(若是單選/多選框,該值無意義,可為0)
      int16_t  val;  //這個列表項關(guān)聯(lián)的顯示的值(可以用于設(shè)置初值) 
      String text;      
      //這個列表項顯示的字符串
      //(通過選項的第一個字符判斷為數(shù)值彈窗(~)/確認彈窗($)/其他項(-)/二值選項框(+)/單選項(=),
        /*注意只有WavePage和DigitalPage的字符串不需要前綴)*/
      //其中二值選項框由于二值項只能在列表中展示,因此只在列表選擇頁面中有效,在磁帖頁面中如果出現(xiàn)+開頭的字串默認為其他項
      //其實單選列表項,需使用其他項在應(yīng)用層關(guān)聯(lián)跳轉(zhuǎn)單選終端頁面實現(xiàn)(單選列表項必須使用=做字符串開頭)。
    } Option; //通用選項類
    

    Option變量的初始化需要注意以下兩點:

    1. 字符串成員 text, 在ListPage和TitlePage頁面都是有前綴的,且前綴是有意義的(用于識別彈窗和選框);text的第一個字符判斷為數(shù)值彈窗(~)/確認彈窗($)/其他項(-)/二值選項框(+)/單選項(=)。

    2. 如果想要一個選項不會受接收消息的控制,如某個數(shù)值變量(如電量,由外部來更改,不是需要設(shè)置的)只是用于展示的,step成員可以設(shè)置為0,這樣即使收到對應(yīng)的up/down消息也不會改變其值。同時,因為將step設(shè)為0時,通常將數(shù)值彈窗當作展示使用,所以此時會在進入數(shù)值彈窗前調(diào)用一次回調(diào)函數(shù)用于給數(shù)值賦值,若step不為0,則只有在數(shù)值彈窗內(nèi)收到click才會調(diào)用回調(diào) 。

    同樣的,對于二值選框(text以"+ "開頭) , 如果step為0,收到up/down消息時也不會取反,只有step不為0時才會取反。

  • CallBackFunc : 回調(diào)函數(shù)類型,每個頁面都需要一個回調(diào)函數(shù)(如果沒有回調(diào)函數(shù),在對應(yīng)初始化函數(shù)中置NULL即可)。

    通常需要定義一個形如void MainPage_CallBack(uint8_t self_page_id,Option* select_item)的函數(shù)(其中,MainPage_CallBack是由我們定義的回調(diào)函數(shù)名(地址)),并該函數(shù)地址作為參數(shù)給對應(yīng)的頁面初始化函數(shù)。

    在頁面中的選項被click時,該頁面的回調(diào)函數(shù)會被調(diào)用,

    傳入回調(diào)函數(shù)的參數(shù)self_page_id 為當前頁面的id(每個頁面都有唯一的id,需要在對應(yīng)頁面初始化時傳入);

    傳入回調(diào)函數(shù)的參數(shù)select_item為當前頁面被選中且click的選項(類型為Option),可以通過讀取該函數(shù)的order得知當前選中的是哪個選項,并在回調(diào)函數(shù)中進行對應(yīng)的處理。

下面會分成6個基礎(chǔ)頁面類型來介紹對應(yīng)的頁面類型,同時說明接口函數(shù)的使用(其實,大部分接口函數(shù)直接看注釋都能明白的??)。

TitlePage類和接口函數(shù)

  • TiltlePage頁面的演示效果如下:

    WouoUI-PageVersion 一個用于快速構(gòu)建具有絲滑OLED_UI動畫的項目,WouoUI Page版,ui,單片機,stm32,oled,絲滑動畫
  • 接口函數(shù)只有一個

    void OLED_TitlePageInit(TitlePage * title_page, uint8_t page_id,uint8_t item_num,Option* option_array,Icon *icon_array,CallBackFunc call_back);

    • 參數(shù)需要有TitlePage 頁面對象的指針,唯一的page_id(每個頁面必須有一個唯一的id);

    • 需要注意的有 :item_num 表示后面 option_array(選項數(shù)組)和 icon_arra(圖標數(shù)組)的數(shù)組大小,三者必須保持一致

    • 同時,option_array 中的選項內(nèi)的text字符串需要有前綴,用于表示該選項的類型

    • "~ " 前綴表示該選項為數(shù)值彈窗

      (在TitlePage頁面使用數(shù)值彈窗可以參考CSource/example下LittleClock的例子)

    • "$ " 前綴表示該選項為確認彈窗

    • 其他前綴為一般選項,沒有特殊意義,需要注意的是TitlePage頁面不會顯示選項的text前綴,因此,對于一般選項,字符串前最好空出兩個空格或者使用"- " 前綴。

    • TitlePage會在選中選項上收到msg_click消息時,調(diào)用一次回調(diào)函數(shù),并將選中的選項傳入。

ListPage類和接口函數(shù)

  • ListPage頁面的演示效果如下:
  • 同樣地,接口函數(shù)只有一個

    void OLED_ListPageInit(ListPage * lp,uint8_t page_id,uint8_t item_num,Option *option_array,CallBackFunc call_back);

    • 參數(shù)需要有ListPage 頁面對象的指針,唯一的page_id(每個頁面必須有一個唯一的id);
    • 同樣需要注意的是:item_num 表示后面option_array(選項數(shù)組)的數(shù)組大小,必須保持一致
    • 同時,option_array選項數(shù)組中text字符串使用前綴表示選項的類型
    • "~ " 前綴表示數(shù)值彈窗
    • "$ " 前綴表示確認彈窗
    • "+ " 前綴表示二值選項框 (會在選項后用一個框,表示是否框選)
    • 其他前綴沒有特殊意義,與TitlePage不同的是,ListPage 會顯示字符串的前綴,用于對齊選項,因此,強烈建議,其他選項使用 "- " 作為字符串前綴。
    • 同樣,ListPage會在選中選項上收到msg_click消息時,調(diào)用回調(diào)函數(shù),并將選中選項傳入回調(diào)函數(shù)。

RadioPage類和接口函數(shù)

  • RadioPage頁面的演示效果如下:

  • 其實,**RadioPage頁面和ListPage頁面是基本一樣的,不同的是,對于使用"= " 作為text前綴的選項來說,RadioPage頁面會將其處理為單選項,即,這個頁面內(nèi),所有使用 "= " 為text前綴的選項只能有一個能被選中,以實現(xiàn)單選的效果。**因為,通常對于這樣的選項頁面,我們一整個頁面內(nèi)都是這種單選項,所以將其單獨作為一個頁面類型拿出。

  • 其接口函數(shù)與ListPage基本一致:(注意事項也請參考上面??)

    void OLED_RadioPageInit(RadioPage * rp, uint8_t page_id, uint8_t item_num,Option *option_array,CallBackFunc call_back);

    唯一一點區(qū)別,可能就是第一個參數(shù)的類型,需要是RadioPage類型。

WavePage類和接口函數(shù)

  • WavePage頁面的演示效果

  • WavePage頁面有兩個接口函數(shù)

  1. void OLED_WavePageInit(WavePage * wp, uint8_t page_id, uint8_t item_num, Option *option_array, CallBackFunc call_back); (照例是初始化函數(shù))

    • 參數(shù)需要有WavePage 頁面對象的指針,唯一的page_id(每個頁面必須有一個唯一的id);

    • 同樣需要注意的是:item_num 表示后面option_array(選項數(shù)組)的數(shù)組大小,必須保持一致

    • 與其他頁面不同的是,WavePage 頁面選項text的字符串前綴均沒有特殊意義,同時也不建議在WavePage頁面使用選項前綴,因為需要顯示波形的關(guān)系,選項字符串的大小最好不要超過5個字符,因此就不加前綴占用多余的字符了

    • 同樣的,WavePage頁面也在選中項上收到msg_click消息時會調(diào)用一次回調(diào)函數(shù)。

  2. void OLED_UIWaveUpdateVal(Option * op, int16_t val);

    • 這個函數(shù)用于更新每個選項的波形值,對應(yīng)的參數(shù)就是要 更新選項的指針更新的值

    • 需要注意以下的是,波形的繪制是與 void OLED_UIProc(void); 這個函數(shù)的調(diào)用一致的。

    因此,建議波形的橫坐標為一個隨著 OLED_UIProc() 函數(shù)調(diào)用 一起自增的變量比較合適。

    (可以參考CSource/example下的UITest例子)


分割線在此,因為,以上的頁面均是WouoUI原作者中的主要頁面元素(再次感謝原作者????);以下是我自己因為項目需要自己增加的兩個頁面,兩個頁面的過渡動畫都使用了和WouoUI一致的動畫。

RaderPicPage類和接口函數(shù)

  • RaderPicPage頁面演示效果:

  • RaderPicPage 類只有一個接口函數(shù)(就是初始化函數(shù))

    void OLED_RaderPicPageInit(RaderPicPage* rpp,uint8_t page_id,uint8_t pic_num,RaderPic * pic_array,RaderPicMode mode,CallBackFunc cb);

    • 參數(shù)需要有RaderPicPage 頁面對象的指針,唯一的page_id(每個頁面必須有一個唯一的id);

    • 需要注意的是,pic_num是后面pic_array數(shù)組的數(shù)組大小,必須保持一致 ,同時,這里有一個RaderPicPage頁面才會用到的類(結(jié)構(gòu)體類型)RaderPic,詳情在下方。

    • 同時,mode成員為一個枚舉類型,用于設(shè)置頁面圖片全部繪制完成后的操作,有兩個可取值

    • Rader_Pic_Mode_Loop : 全部圖片繪制結(jié)束后,清空頁面,從頭重新繪制

    • Rader_Pic_Mode_Hold : 全部圖片繪制結(jié)束后,保持繪制完成的頁面。

    • 需要注意的另外一點是, RaderPicPage頁面沒有選項,所以回調(diào)函數(shù)會在每一個圖片繪制完成后調(diào)用,將該圖片的順序( 1 ~ pic_num ), 作為Option的order傳入RaderPicPage的回調(diào)函數(shù),可以在回調(diào)函數(shù)中接收Option的order以判斷第幾張圖片已經(jīng)繪制完成,再執(zhí)行對應(yīng)的操作。

    • 這兒需要注意,如果是頁面處于 Rader_Pic_Mode_Hold 模式的話,所有圖片繪制結(jié)束后,處于保持狀態(tài),會持續(xù)調(diào)用回調(diào)函數(shù),并傳入第pic_num張圖片已繪制完成的Option(Option的order成員的值為pic_num)。

  • RaderPic類,鐳射圖片類型,其結(jié)構(gòu)體成員如下:

    typedef struct 
    {
        const uint8_t * pic; //圖片指針
        int16_t start_x;    //起始x坐標
        int16_t start_y;    //起始y坐標
        uint8_t w;          //圖片的寬
        uint8_t h;          //圖片的高
        RaderDirection rd;  //控制繪制時的射線方向選擇,枚舉類型
    } RaderPic; //鐳射圖片對象
    

    其中結(jié)構(gòu)體成員rd 為一個枚舉類型 RaderDirection 變量,其可以有的取值有:

    typedef enum
    {
        RD_LEFT_UP = 0x00, //射線從左上角出發(fā)
        RD_LEFT_DOWN,      //射線從左下角出發(fā)
        RD_RIGHT_UP,       //射線從右上角出發(fā)
        RD_RIGHT_DOWN,	   //射線從右下角出發(fā)
        RD_RIGHT,		   //射線從水平向右
        RD_LEFT, 		   //射線從水平向左
    } RaderDirection;
    

DigitalPage類和接口函數(shù)

DigitalPage 頁面演示效果:
DigitalPage 頁面相關(guān)的接口函數(shù)有三個:
  • void OLED_DigitalPageInit(DigitalPage* dp, uint8_t page_id, Option * option_array, uint8_t label_array_num, String * label_array, char gap_char, uint8_t gap_shine_time, uint8_t uline_shine_time,CallBackFunc cb);

    • 參數(shù)需要有DigitalPage 頁面對象的指針,唯一的page_id(每個頁面必須有一個唯一的id);

    • 需要注意的參數(shù)有:

    • option_array: 這個選項數(shù)組的大小必須為3,因為3個選項分別表示DigitalPage頁面中3個兩位的十進制數(shù)字。

    • label_array_num 為后面參數(shù) label_array 標簽數(shù)組的數(shù)組大小,必須保持一致。(其中,String 類型就是 char*, 在使用時,可以直接使用String 類型,具體可以參考 CSource/example下的UITest例子)

    • gap_char 為3個兩位十進制數(shù)字間的單個分隔字符,gap_shine_timeuline_shine_time 用于控制 分隔字符 和 編輯時出現(xiàn)的下劃線 的閃爍間隔,閃爍周期為 OLED_UIProc()函數(shù)運行一次的時間間隔 乘以 參數(shù)設(shè)置值。

    • 在DigitalPage 頁面,編輯每個數(shù)字(或者是標簽)后收到msg_click 消息 是會觸發(fā)一次回調(diào),將 對應(yīng)數(shù)字的Option 或者 標簽賦值的text的Option 傳入回調(diào)函數(shù),以便接收click時的選中的數(shù)字或者標簽字符串的值。 建議在回調(diào)函數(shù)中檢查option中的order時,使用DigitalPosIndex枚舉類型進行判斷。

    typedef enum //Digital頁面從右往左為indexRigit到indexLeft
     {
         Digital_Pos_IndexRight = 0x00, //用于指示當前光標或者編輯的位置
         Digital_Pos_IndexMid,
         Digital_Pos_IndexLeft,
         Digital_Pos_IndexLabel,  //在標簽處
         Digital_Pos_Complete,   //編輯完成
     }DigitalPosIndex; //用于在回調(diào)函數(shù)中檢驗選中項的op->order值,表示選中哪個數(shù)字位還是標簽
    

    同時,在DigitalPage頁面退出編輯模式(返回觀察模式)時,也會調(diào)用一次回調(diào)函數(shù)函數(shù),并傳入的order為Digital_Pos_Complete的一個option , 所以在回調(diào)函數(shù)中判斷這個order,可以將對應(yīng)的操作放在編輯結(jié)束返回到觀察模式時執(zhí)行(例如,等所有值設(shè)置結(jié)束再讀取值)。

  • void OLED_DigitalPage_UpdateDigitalNumAnimation(DigitalPage * dp, uint8_t leftval, uint8_t midval, uint8_t rightval, DigitalDirect dir);

    • 用于更新DigitalPage頁面中的數(shù)字,并觸發(fā)滾動的動畫。
    • 需要注意的是,dirDigitalDirect 枚舉類型的一個變量,可取的值有 Digital_Direct_Increase , Digital_Direct_Decrease 兩種,決定數(shù)字的滾動方向。
  • void OLED_DigitalPage_UpdateLabelAnimation(DigitalPage * dp, uint8_t label_index, DigitalDirect dir)

    • 用于更新DigitalPage頁面中的標簽,并觸發(fā)滾動的動畫。

    • 需要注意的是,只能將標簽更新為初始化中設(shè)置的 label_array 標簽數(shù)組中的一個便簽。label_index 為要更新的標簽在 label_array 的下標(取值0~label_num_array -1);label_index可以超過 label_num_array ,當超過時會自動選擇為0。

    dir 與更新數(shù)字的函數(shù)一樣,是 DigitalDirect 枚舉類型的一個變量,可取的值有 Digital_Direct_Increase , Digital_Direct_Decrease 兩種,決定的滾動方向。

DigitalPage頁面操作邏輯的說明

DigitalPage類(結(jié)構(gòu)體類型)中有一個比較重要的成員mode (為枚舉類型 DigitalMode) 。該枚舉類型的取值有如下幾個

typedef enum
{
    Digital_Mode_Observe = 0x00,   
    //觀察模式?jīng)]有光標(剛進入DigitalPage頁面的模式;沒有下劃線光標)
    Digital_Mode_Edit    = 0x01,   
    //對編輯位置的編輯(可以通過up\down消息控制光標的移動;下劃線光標閃爍)
    Digital_Mode_Singlebit = 0x02, //對單位數(shù)字的編輯(可以通過up\down消息控制單位數(shù)字/標簽的加減和切換;下劃線光標常亮)
} DigitalMode; //digital頁面的模式

DigitalPage頁面運行的狀態(tài)機如下圖所示:有興趣的可以看看??

WouoUI-PageVersion 一個用于快速構(gòu)建具有絲滑OLED_UI動畫的項目,WouoUI Page版,ui,單片機,stm32,oled,絲滑動畫

UI的一些接口函數(shù)和參數(shù)

一些UI使用的接口函數(shù)和參數(shù)一起在這兒說明。

接口函數(shù)(有6個)
//用于向UI傳遞一個消息Msg(msg_click/msg_up/msg_down/msg_return)
void OLED_MsgQueSend(InputMsg msg);
//UI必要的一些參數(shù)和變量的初始化
void OLED_UiInit(void);
//UI運行任務(wù),需要放在主循環(huán)中循環(huán)調(diào)用,而且盡量不要阻塞
void OLED_UIProc(void);
//從一個頁面跳轉(zhuǎn)到另一個頁面,常用于回調(diào)函數(shù)中調(diào)用,并確定頁面的上下級關(guān)系(這樣,在terminate_page頁面收到return消息時,會返回self_page_id所代表的頁面)
//@param self_page_id 是當前頁面的id(回調(diào)函數(shù)中有這個參數(shù))
//@param  terminate_page 要跳轉(zhuǎn)的那個頁面的地址(不需要理會是那種類型的頁面,直接將頁面地址作為參數(shù)傳入即可)
void OLED_UIJumpToPage(uint8_t self_page_id,PageAddr terminate_page);
//切換當前頁面的函數(shù),與Jump函數(shù)不同的時,這個函數(shù)不會綁定上下級頁面關(guān)系,
//terminate_page 頁面收到return 消息不會返回當前頁面(常用于臨時的畫面切換)
//@param terminate_page 要跳轉(zhuǎn)的那個頁面的地址(不需要理會是那種類型的頁面,直接將頁面地址作為參數(shù)傳入即可)
void OLED_UIChangeCurrentPage(PageAddr terminate_page);
/*獲取當前頁面的id*/
uint8_t OLED_UIGetCurrentPageID(void);

需要注意的只有:

  1. void OLED_UIProc(void); 需要在主循環(huán)中循環(huán)調(diào)用,且最好沒有阻塞;
  2. OLED_UIJumpToPage 函數(shù)會確認頁面的上下級關(guān)系,OLED_UIChangeCurrentPage 函數(shù)只是切換頁面,沒有確認頁面的上下級關(guān)系;
  3. OLED_UIJumpToPage 函數(shù)和OLED_UIChangeCurrentPage 函數(shù) 的terminate_page 參數(shù)只需傳入頁面地址(指針)就行,不需要理會頁面是什么類型。
UI參數(shù)

WouoUIPage的參數(shù)基本上WouoUI原作保持一致,如下:(由于我沒有移植退出時的淡出動畫,因此參數(shù)也會比WouoUI要少一些)

  ui_para.ani_param[TILE_ANI] = 120;  // 磁貼動畫速度
  ui_para.ani_param[LIST_ANI] = 120;  // 列表動畫速度
  ui_para.ani_param[WIN_ANI] = 120;   // 彈窗動畫速度
  ui_para.ani_param[TAG_ANI] = 60;   // 標簽動畫速度
  ui_para.ani_param[DIGI_ANI] = 100;  // 數(shù)字動畫滾動速度(這些速度是越大運動越慢)
  ui_para.ufd_param[TILE_UFD] = True;   // 磁貼圖標從頭展開開關(guān)
  ui_para.ufd_param[LIST_UFD] = True;   // 菜單列表從頭展開開關(guān)
  ui_para.loop_param[TILE_LOOP] = True;  // 磁貼圖標循環(huán)模式開關(guān)
  ui_para.loop_param[LIST_LOOP] = True;  // 菜單列表循環(huán)模式開關(guān)
  ui_para.valwin_broken = True;           //彈窗背景虛化開關(guān)
  ui_para.conwin_broken = True;           //確認彈窗背景虛化開關(guān)
  ui_para.digital_ripple = True;           //digital頁面波紋遞增動畫開關(guān)
  ui_para.raderpic_scan_mode = False;     //鐳射文字只掃描亮處
  ui_para.raderpic_scan_rate = 4;        //鐳射文字掃描速度
  ui_para.raderpic_move_rate = 50;        //鐳射文字移動速度

WouoUIPage整體的代碼邏輯

這部分是針對想要二次開發(fā)WouoUIPage的人寫的(其實是怕我之后回來想做改進的時候看不懂自己的代碼??),方便理解整體的代碼邏輯,如果是單純使用的話,參考例子和上面的接口說明應(yīng)該就夠了。

關(guān)于圖形層

  • 圖形層中有一個window 類,這個類幾乎在每個圖形層的函數(shù)中都是作為第一個參數(shù)輸入的。這個window 只是用于控制繪制的邊界,繪圖函數(shù)繪制的點如果超過傳入的window 的大小,就不會繪制到緩沖區(qū)中。

    oled_ui.h 中提供了一個w_all 全局窗口變量,只是為了方便可能在除了上述頁面之外,使用者還有其他繪圖需要準備的,其邊界為整個128*64的屏幕,這個窗口也是整個ui繪制時主要使用的窗口。

  • 圖形層中有一個更改畫點顏色的函數(shù):(其實是控制寫入的字節(jié)以什么位運算寫入緩沖區(qū)中)。

    /**
    * @brief : void OLED_SetPointColor(uint8_t color)
    * @param : 設(shè)置畫筆顏色,color:1=亮,0=滅,2=反色
    * @attention : None
    * @author : Sheep
    * @date : 23/10/04
    */
    void OLED_SetPointColor(uint8_t color)
    {
    	switch (color)
    	{
    		case 0: oled_color = '&';break;
    		case 1: oled_color = '|';break;
    		case 2: oled_color = '^';break;
    		default:break;
    	}
    	// oled_color = (color != 0 )?'|':'&';
    } 
    

關(guān)于UI層

  • PageAddr 頁面地址變量,其實是一個 void* 類型,為了用于實現(xiàn) OLED_UIJumpToPage 函數(shù)和 OLED_UIChangeCurrentPage 函數(shù)的 “偽多態(tài)”。(其實內(nèi)部所有AnimInit 、 Show 、 React 函數(shù)都使用這樣的"偽多態(tài)") 。

    在獲取頁面地址后,直接強轉(zhuǎn)為 Page 類,這是一個所有頁面類型都必須包含的結(jié)構(gòu)體成員(且必須是第一個,為了方便轉(zhuǎn)換類型)。Page 類中包含了所有頁面必須有的一些成員,如下:

    //每個頁面都有的三種方法
    typedef void (*PageAniInit)(PageAddr);  //頁面的動畫初始化函數(shù)
    typedef void (*PageShow)(PageAddr);    //頁面的展示函數(shù)
    typedef void (*PageReact)(PageAddr);  //頁面的響應(yīng)函數(shù)
    typedef struct 
    {
      PageType page_type; //頁面類型,以便在處理時調(diào)用不同函數(shù)繪制
      uint8_t page_id; //頁面的序號,每個頁面唯一一個,用于指示在數(shù)組中的位置,方便跳轉(zhuǎn)
      uint8_t last_page_id; //上一個頁面的id,用于返回時使用
      CallBackFunc cb; //頁面的回調(diào)函數(shù)
      PageAniInit ani_init; 
      PageShow show;
      PageReact react;
    } Page; //最基本的頁面類型(所有頁面類型的基類和結(jié)構(gòu)體的**第一個成員**)
    
  • WouoUIPage的狀態(tài)機(相比WouoUI原版減少了一個”退出過渡動畫“,原因就是 Air001的RAM和Flash不太夠??)。

    WouoUI-PageVersion 一個用于快速構(gòu)建具有絲滑OLED_UI動畫的項目,WouoUI Page版,ui,單片機,stm32,oled,絲滑動畫

關(guān)于注釋

如果有小伙伴愿意查看源代碼的話,可能會看到有三種風格的函數(shù)注釋,這是因為我本身有兩種函數(shù)注釋風格,而且在后期寫代碼的過程中,使用了阿里的大模型幫忙生成注釋,因此注釋可能會有多種風格??。文章來源地址http://www.zghlxwxcb.cn/news/detail-834787.html

到了這里,關(guān)于WouoUI-PageVersion 一個用于快速構(gòu)建具有絲滑OLED_UI動畫的項目的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包