Flutter 是一個可以用同一份 Codebase 建構不同平台的應用程式的框架,例如:Android、iOS … 甚至 Web、Windows 等等。每個平台的使用者行為與設計原則並非完全相同。有時候我們會為了優化個平台使用者的體驗,而在不同平台使用不同設計樣式。以下面的例子來說,Android 上常見的開關樣式與 iOS 長得十分不同。
為了完成這個功能,我們在 build 方法中當前平台,來決定使用哪種設計。
https://dartpad.dev/?id=418d5126a81bf9a1926245a64b90c2fb
在 Flutter 中,一些 Widget 提供了 adaptive 方法,讓開發者更容易實現不同樣式,例如 Switch.adaptive、Slider.adaptive、CircularProgressIndicator.adaptive 等等。使用 Widget 前,查看一下 API 文件,避免重造輪子是一個務實的做法。
https://dartpad.dev/?id=ca3739f1104d0eca8b2a1232b9f75bf9
若我們修改一下上面的例子,使用 adaptive 方法的話,就會省事許多。但並非所有情況我們都能使用 adaptive,有些時候是 Widget 本身沒有 adaptive 的設計,有些時候我們想要的情況更為複雜,此時我們只好自己判斷平台自己決定如何顯示。
當今天有很多地方都需要根據平台製作不同樣式時,我們可能會在許多 Widget 中,都有判斷平台的程式碼。
https://dartpad.dev/?id=b63ab14d0523afb6810b3c74c592abd8
此時為了解決這個問題,我們可以使用樣板模式來解決,把重複的判斷邏輯到放 PlatformWidget 中,並提供 buildMaterial 和 buildCupertino 的方法讓實作決定。
https://dartpad.dev/?id=89ff992117cc2a0a90d0b3fb3ff032a0
當今天需要新增一個跨平台的 Widget 時,我們就能繼承這個方法,並提供不同平台的實現,就在每個跨平台 Widget 中重複判斷了。
當我們使用 PlatformWidget 來修改上一段例子後,原本的判斷平台邏輯就不見了 MyInfoScreen 只要專注於如何實現兩個平台的設計。
今天討論如何讓設計支援多個 Platform 的問題,也討論如何使用繼承與樣板模式來解決問題。但其實問題不只限於如何判斷 Platform,我們常常都會使用 if else 來協助處理流程的分岔,如何在需要的時候善用方法來解決散落各地的流程分岔是一個難題,並非總是要使用繼承來解決問題,需要讀者在開發時多多思考,並選擇最合適的方式。
今天的範例,大多無法使用 Dartpad 執行,還請想要動手試試的讀者們,自行複製程式碼到自己的 IDE 上執行。