前言:
這是我參與8月更文挑戰的第 27 天,活動詳情檢視:8月更文挑戰。為應掘金的八月更文挑戰
,我準備在本月挑選 31
個以前沒有介紹過的元件,進行全面分析和屬性介紹。這些文章將來會作為 Flutter 元件集錄
的重要素材。希望可以堅持下去,你的支援將是我最大的動力~
1.認識 DecoratedBox 元件
DecoratedBox
元件可能單獨使用的頻率不是很高,因為它被整合在了 Container
元件中,但裝飾的使用方式是共通的,原始碼中說 DecoratedBox
會在其孩子的前景或背景上繪製 Decoration
裝飾物件。這說明 Decoration
才是裝飾的重點,我們需要了解或自定義 Decoration
。
下面是 DecoratedBox
元件類的定義
和 構造方法
,可以看出它繼承自 SingleChildRenderObjectWidget
。構造時必須傳入尺寸 decoration
引數,可以傳入 position
入參。
decoration
成員的型別是 Decoration
,表示裝飾物件。position
成員的型別是 DecorationPosition
列舉,表示在前景繪製還是在背景繪製。
final Decoration decoration;
final DecorationPosition position;
enum DecorationPosition {
background,
foreground,
}
複製程式碼
2.認識 Decoration 及其子類
首先需要注意的是: Decoration
是一個抽象類,無法直接例項化使用。
Flutter
框架中提供了四個實現類,其中 BoxDecoration
是我們最常用的。
比如下面通過 BoxDecoration
的 borderRadius
可以指定裝飾的圓角,通過 color
指定填充的顏色。
DecoratedBox(
decoration: BoxDecoration(
color: Colors.orangeAccent,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20),
bottomRight: Radius.circular(20),
bottomLeft: Radius.circular(5),
topRight: Radius.circular(5),
),
),
child: buildContent(),
);
Widget buildContent() {
return SizedBox(
width: 80,
height: 80,
child: Icon(Icons.android, size: 50, color: Colors.white),
);
}
複製程式碼
下面是 BoxDecoration
的構造方法,可以看出除了圓角和顏色,還有很多入參,比如背景圖片
、邊線
、陰影
、漸變
、形狀
等。
如下裝飾,有紅色史詩碎片那味了:
BoxDecoration(
color: Colors.transparent,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20),
bottomRight: Radius.circular(20),
bottomLeft: Radius.circular(5),
topRight: Radius.circular(5),
),
border: Border.all(color: Colors.red, width: 2),
image: DecorationImage(
image: AssetImage('assets/images/bg_6.jpeg'),
fit: BoxFit.cover,
),
boxShadow: [
const BoxShadow(
color: Colors.red,
offset: Offset.zero,
blurRadius: 2,
spreadRadius: 2),
]
),
複製程式碼
另外還有一個 ShapeDecoration
子類,顧名思義,它可以進行一些形狀的處理。其中入參必須傳入 ShapeBorder
型別的 shape
引數。關於 ShapeBorder
,詳見 : 《Path在手,天下我有》
如下,通過一個 Flutter 自帶的 CircleBorder
來測試一下:
DecoratedBox(
position: DecorationPosition.background,
decoration: ShapeDecoration(
shape: CircleBorder(),
shadows: const [BoxShadow(
color: Colors.red,
offset: Offset.zero,
blurRadius: 2,
spreadRadius: 2)],
image: DecorationImage(
image: AssetImage('assets/images/bg_6.jpeg'),
fit: BoxFit.cover,
),
),
child: buildContent(),
);
複製程式碼
3.自定義裝飾
很多人問過我,如何加虛線邊框。本質上就是在問如何通過繪製虛線,通過 DecoratedBox
裝飾而已。在我釋出的 dash_painter 包中有實現虛線裝飾,就以此來講述一下如何自定義裝飾
。
dependencies:
...
dash_painter: ^1.0.2
複製程式碼
import 'package:dash_painter/dash_decoration.dart';
DecoratedBox(
decoration: DashDecoration(
pointWidth: 2,
step: 5,
pointCount: 1,
radius: Radius.circular(15),
gradient: SweepGradient(colors: [
Colors.blue,
Colors.red,
Colors.yellow,
Colors.green
])),
child: buildContent(),
);
Widget buildContent() {
return SizedBox(
width: 70,
height: 70,
child: Icon(
Icons.add, color: Colors.orangeAccent, size: 40),
);
}
複製程式碼
下面看一下 DashDecoration
的原始碼實現,首先定義可配置的引數,通過建構函式初始化。
在 DashDecoration
中必須實現抽象方法 createBoxPainter
,返回一個 BoxPainter
物件。
然後繼承 BoxPainter
,將配置物件傳進來,在 paint
裡畫就完事了。本身流程很簡單,關鍵在於如何繪製。在 《Flutter 繪製指南 - 妙筆生花》 小冊中系統地介紹了 Flutter 繪製相關的基礎知識,感興趣的可以看一看。
4. DecoratedBox 的原始碼實現
DecoratedBox
繼承自 SingleChildRenderObjectWidget
,內部維護 RenderDecoratedBox
渲染物件來實現裝飾功能。
核心程式碼是下面的 paint
方法,執行繪製。其中 super.paint(context, offset);
是繪製子元件,可見 background
是在繪製孩子前繪製,也就是作為背景,孩子在前面。而 foreground
會覆蓋在孩子前面,也就是前景。畫筆是通過 _decoration#createBoxPainter
建立的,也就是那個 BoxPainter
物件。
那本文到這裡就結束了,謝謝觀看,明天見~