在開發 App 的過程中,我們會有許多常數,例如圖片位置、文字樣式、元件顏色等等。如果我們把所有顏色,樣式或路徑都寫死在程式中,就會造成後續修改十分不方便,也降低得了程式碼的可讀性。
在開發應用程式的過程中,我會從設計手中拿到設計稿,其中標注了各式各樣的字型大小與顏色樣式,我們把依照設計稿,把顏色與樣式帶入程式碼中,最終完成畫面。
https://dartpad.dev/?id=ac17d00aad388ac473e8698d81b923c0
大多時候,我們會在同一個應用程式中,維持相似的設計,以提供使用者一致的體驗。所以相同的字體、樣式、或顏色會重複的出現在不同畫面中。若我們在每個地方再複製一次,當今天想為應用程式更換設計時,就會需要到每個實作的地方修改。
除此之外,我們也常常會使用到圖片,無碖是各式各樣的 Icon 或者是背景圖,免不了的一定會使用圖片。
如果我們直接在程式碼中使用路徑,容易造成幾個問題:
為了解決這些問題,我們可以把這些共用的設計樣式,抽取一個共同的樣式清單,並為每一個樣式給予一個符合設計意義的名稱。
https://dartpad.dev/?id=63908ad88cb4a8fb200b6fce1482bd13
當實際使用時,除了共用這些相同意義的設計之外,也能讓程式碼與設計稿有更直觀連結。
甚至我們也可以使用先 extension 簡化寫法。
https://dartpad.dev/?id=2964d51eb07b99ee4ee673c28838b911
當我們處理完文字樣式與顏色之後,我們還可以使用 flutter_gen 簡化顯示圖片的程式碼。當我們按照指示引用 flutter_gen 與 build_runner 之後,執行 build_runner 就能幫我們產生程式碼。
https://dartpad.dev/?id=f6a5b8263d0db41e8487f071dec59741
而使用實際只用只要呼叫 Assets 的程式碼,就能像是使用 Image.asset() 一樣,在畫面上顯示圖片。
Assets.icons.addFriend.image(width: 20)
使用程式碼來選擇圖片,有一個很大的優點就是,寫程式時搭配 IDE 的功能,讓我們按最少的按鍵,以最有效率的方式寫完我們想要的程式碼。
當我們做完了上述工作,把樣式、顏色、圖片等等資源,抽成常數之後,我們程式碼有了兩個主要好處。
在上面的例子中,我們把設計放在一個靜態類別中,在渲染畫面時,直接飲用這些靜態變數。如果樣式在程式執行時不會動態切換,那直接引用這個靜態的設計類別並不會有太大的問題。但真實的情況是,假設我們想為我們的 App 製作 Light/Dark 模式,並讓使用者可以動態切換。此時,由於我們的 Widget 直接引用了靜態類別,使得我們難以動態改變樣式。為了解決這個問題,我們可以使用 ThemeExtension 來解決問題。
https://dartpad.dev/?id=15705a2e37befec46ff388113c29bd23
使用時,就能透過 Theme.of(context).extension() 動態取得當前的樣式。當我們修改頂層樣式,從 light 切換成 dark 時,Flutter 也重新渲染畫面,讓這些樣式可以再次取得更改之後的 dark 樣式。
使用 ThemeExtension 取代靜態樣式類別,除了能保有自定義的樣式設計,也能讓我們程式具備動態切換樣式的能力。
在開發客端應用程式時,設計師往往都會使用一些設計原則,並套用在設計稿上。當我們開發時,也把相同的設計原則直接用程式碼實作,這樣能讓程式碼與設計有一致的語言。未來當設計變化時,程式也能直接跟著設計調整,而不用辛苦一個一個地方修改。