起因
有個小夥伴在群裡問了這樣一個問題:
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」,
大佬翻譯了一下 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
時的顏色。
MaterialType
你以為到這裡就結束了?不,我還要看一下這個 type 都有什麼型別:
enum MaterialType {
/// 使用預設主題畫布顏色的矩形。
canvas,
/// 圓形邊緣,卡片主題顏色。
card,
/// 預設情況下沒有顏色的圓(用於浮動操作按鈕)。
circle,
/// 圓形邊緣,預設情況下沒有顏色(用於[MaterialButton]按鈕)。
button,
/// 一塊透明的材料,用於繪製噴墨和高光。雖然材料隱喻描述了列印在材料本身上的子部件,但不隱藏墨跡效 果,但實際上[Material]小部件將子部件繪製在墨跡效果的頂部。具有型別透明度的[材質]可以放置在 不透明小部件的頂部,以在其頂部顯示墨跡效果。首選使用[ink]小部件在不透明小部件上顯示墨跡效果。
transparency
}
複製程式碼
不用猜了,上面中文都是我用翻譯軟體翻譯出來的!
那既然如此,我們改一下這個 type,把它改為 canvas
,看看還是不是紅色了:
總結
雖然裝逼失敗了,但是我個人對於 Theme 這方面的理解更深了,
而且以後如果有定義 Widget 的需求的話,也可以使用該方法,定義一個 Material
的 type,
這樣就可以和整個APP的風格保持一致了。