Flutter | 一個關於背景顏色引發的打臉慘案

Flutter筆記發表於2019-08-07

起因

有個小夥伴在群裡問了這樣一個問題:

PopupMenuButton 怎麼改背景色?

這不正好撞槍口上了麼,剛寫完 PopupMenuButton 的文章,這個逼必須得裝。

Flutter | 一個關於背景顏色引發的打臉慘案

趕緊去翻原始碼,發現 PopupMenuButton 本身並沒有提供改變顏色的引數,

那沒辦法了,只能找彈出頁面的原始碼了。

找了半天找到了返回彈出框的地方,加了一個 Container,設定了一個 color,大功告成!

於是,我發了這樣的文字:

popup_menu.dart 466行,加個 Container 設定一下顏色就行了

功成身退!

Flutter | 一個關於背景顏色引發的打臉慘案

本以為該群友會發出這樣的感嘆:

哇,大佬牛逼牛逼!

如何如何...

然而,命運多舛,裝逼的道路總是這麼坎坷。不然我也不會寫這篇文章了。

另一個群友這樣說到:

他:「不能用 Theme 來搞定這個事嗎?」

我:「不能,它沒根據 Theme 來設定顏色,你可以翻原始碼看一下。」

他:「圖片 + 連結」

我(內心 OS):「臥槽,裝逼失敗了?趕緊去看看什麼情況!」

經過

開啟連結,看到是用 Theme 包裹住 PopupMenuButton,然後定義了一個 cardColor,這是什麼操作?

我趕緊去試了試:

Theme(
  data: ThemeData(cardColor: Colors.red),
  child: PopupMenuButton<WhyFarther>(
    // ...
  ), 
),
複製程式碼

直接在上次的程式碼中加入了一個 Theme,並且設定顏色為紅色。

除錯啟動!

Flutter | 一個關於背景顏色引發的打臉慘案

emmmmmmmmmm,

Flutter | 一個關於背景顏色引發的打臉慘案

那麼這個時候問題來了,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,看看還是不是紅色了:

Flutter | 一個關於背景顏色引發的打臉慘案

總結

雖然裝逼失敗了,但是我個人對於 Theme 這方面的理解更深了,

而且以後如果有定義 Widget 的需求的話,也可以使用該方法,定義一個 Material 的 type,

這樣就可以和整個APP的風格保持一致了。

img

相關文章