起因
有個小夥伴在群裡問了這樣一個問題:
PopupMenuButton 怎麼改背景色?
這不正好撞槍口上了麼,剛寫完
PopupMenuButton
的文章,這個逼必須得裝。

趕緊去翻源碼,發現
PopupMenuButton
本身并沒有提供改變顔色的參數,
那沒辦法了,隻能找彈出頁面的源碼了。
找了半天找到了傳回彈出框的地方,加了一個
Container
,設定了一個 color,大功告成!
于是,我發了這樣的文字:
popup_menu.dart 466行,加個 Container 設定一下顔色就行了
功成身退!
本以為該群友會發出這樣的感歎:
哇,大佬牛逼牛逼!
如何如何...
然而,命運多舛,裝逼的道路總是這麼坎坷。不然我也不會寫這篇文章了。
另一個群友這樣說到:
他:「不能用 Theme 來搞定這個事嗎?」
我:「不能,它沒根據 Theme 來設定顔色,你可以翻源碼看一下。」
他:「圖檔 + 連結」
我(内心 OS):「卧槽,裝逼失敗了?趕緊去看看什麼情況!」
經過
打開連結,看到是用
Theme
包裹住
PopupMenuButton
,然後定義了一個
cardColor
,這是什麼操作?
我趕緊去試了試:
Theme( data: ThemeData(cardColor: Colors.red), child: PopupMenuButton<WhyFarther>( // ... ), ),
複制
直接在上次的代碼中加入了一個 Theme,并且設定顔色為紅色。
調試啟動!
emmmmmmmmmm,
那麼這個時候問題來了,
cardColor
是個什麼玩意?
ThemeData
我們都知道,可以定義 Theme 來控制全局的顔色文字之類的,但是我從來不知道有個
cardColor
,
找資料!
功夫不負有心人,讓我找到了 簡書大佬「Magician」寫的 「Flutter:Theme」[1],
大佬翻譯了一下 ThemeData 的主要屬性,其中就包括
cardColor
:
cardColor -類型,
Color
被用作
Material
時的顔色。
Card
什麼亂七八糟的,
Material
被用作
Card
?
當時我就氣不打一處來,我看了半天源碼,也沒見哪個 build 傳回了 Card!
沒辦法,全局搜尋 card 關鍵字!總能看出來問題!
Material
終于在我的不懈努力查找下,找到了可疑之處:
return Opacity( opacity: opacity.evaluate(route.animation), child: Material( type: MaterialType.card, /// ... ), ),);
複制
這個
Material
元件下有個
type
參數,該參數竟然定義為了一個
MaterialType.card
!
不是你還能是誰!
這回終于了解了上述文字:
cardColor -類型,
Color
被用作
Material
時的顔色。
Card
Material.type
你以為到這裡就結束了?不,我還要看一下這個 type 都有什麼類型:
enum MaterialType { /// 使用預設主題畫布顔色的矩形。 canvas,
/// 圓形邊緣,卡片主題顔色。 card,
/// 預設情況下沒有顔色的圓(用于浮動操作按鈕)。 circle,
/// 圓形邊緣,預設情況下沒有顔色(用于[MaterialButton]按鈕)。 button,
/// 一塊透明的材料,用于繪制噴墨和高光。雖然材料隐喻描述了列印在材料本身上的子部件,但不隐藏墨迹效 果,但實際上[Material]小部件将子部件繪制在墨迹效果的頂部。具有類型透明度的[材質]可以放置在 不透明小部件的頂部,以在其頂部顯示墨迹效果。首選使用[ink]小部件在不透明小部件上顯示墨迹效果。 transparency}
複制
不用猜了,上面中文都是我用翻譯軟體翻譯出來的!
那既然如此,我們改一下這個 type,把它改為
canvas
,看看還是不是紅色了:
總結
雖然裝逼失敗了,但是我個人對于 Theme 這方面的了解更深了,
而且以後如果有定義 Widget 的需求的話,也可以使用該方法,定義一個
Material
的 type,
這樣就可以和整個APP的風格保持一緻了。