前言:
這是我參與8月更文挑戰的第 28 天,活動詳情檢視:8月更文挑戰。為應掘金的八月更文挑戰
,我準備在本月挑選 31
個以前沒有介紹過的元件,進行全面分析和屬性介紹。這些文章將來會作為 Flutter 元件集錄
的重要素材。希望可以堅持下去,你的支援將是我最大的動力~
1.認識 BackdropFilter 元件
BackdropFilter
元件可能很少人使用,但它的功能還是很強大的。原始碼中對它的介紹是:對已有的繪製內容新增一個過濾器,然後再繪製它的孩子。
下面是 BackdropFilter
元件類的定義
和 構造方法
,可以看出它繼承自 SingleChildRenderObjectWidget
。構造時必須傳入尺寸 filter
引數,其型別是 ImageFilter
。
final ui.ImageFilter filter;
複製程式碼
2.BackdropFilter 的使用
原始碼中有一個 BackdropFilter
元件的測試案例,我們先基於這個案例,看一下 BackdropFilter
的效果及作用。下圖中,有三個區域: 01文字
、紫色區域
、Hello World
文字。實現的方式是:通過 Stack
疊合 01文字
和 BackdropFilter
,其中紫色區域和Hello World
文字是 BackdropFilter
的子元件。
class CustomBackdropFilter extends StatelessWidget {
final Random random = Random();
@override
Widget build(BuildContext context) {
String data = '';
for (int i = 0; i < 10000; i++) {
data += random.nextBool() ? " 0 " : " 1 ";
}
return Stack(
children: <Widget>[
Text(data),
Center(child: buildFilterZone(),),
],
);
}
Widget buildFilterZone() {
return BackdropFilter(
filter: ui.ImageFilter.blur(
sigmaX: 2.0,
sigmaY: 2.0,
),
child: Container(
alignment: Alignment.center,
width: 200.0,
height: 120.0,
color: Colors.purple.withOpacity(0.1),
child: const Text(
'Hello World',
style: TextStyle(fontSize: 24),
),
),
);
}
}
複製程式碼
從佈局檢視器中可以看出:BackdropFilter
的區域只是紫色部分,模糊遮罩並不會對其子元件
產生影響。就像是在元件上層覆蓋一個模糊層
,而是子元件
會在模糊層
之上。
有時我們可能只是對某個區域進行遮罩處理,可以通過 ClipRRect
等裁剪元件進行裁剪,這樣模糊層
就不會影響之外的部分。如下是圓角矩形的裁剪效果:
ClipRRect(
borderRadius: BorderRadius.circular(20),
child: buildFilterZone(),
),
複製程式碼
3. 認識 ImageFilter
首先 ImageFilter
是一個抽象類,但它可以通過命名構造建立物件,如下有三種構造方式。
拿 ImageFilter.blur
來說,可以看到構造前面有一個 factory
關鍵字,以此讓抽象類也可以建立物件。可以看出這個構造本質上是使用了 _GaussianBlurImageFilter
,也就是高斯模糊
。兩個入參 sigmaX
和 sigmaY
是模糊的程度。
比如下面是 x:2.0,y:2.0
的效果:
這是 x:4.0,y:1.0
的效果:
這是 x:6.0,y:6.0
的效果:
可見 sigmaX
和 sigmaY
分別控制 X
和 Y
方向上的模糊程度。
除了通過 ImageFilter.blur
建立 模糊遮罩
,還可以通過 ImageFilter.matrix
對區域內進行矩陣變換,如下面的 skewX
。
Widget buildFilterZone() {
return BackdropFilter(
filter:
ui.ImageFilter.matrix(Matrix4.skewX(45/180*pi).storage),
child: Container(
alignment: Alignment.center,
width: 200.0,
height: 120.0,
color: Colors.blueAccent.withOpacity(0.1),
child: const Text(
'Hello World',
style: TextStyle(fontSize: 24),
),
),
);
}
複製程式碼
4. BackdropFilter 元件的原始碼實現
BackdropFilter
繼承自 SingleChildRenderObjectWidget
,內部維護 RenderBackdropFilter
渲染物件來實現新增濾色器功能。
在 RenderBackdropFilter#paint
中建立 BackdropFilterLayer
物件 layer
,並將傳入的 filter
設定給 layer
。通過 context.pushLayer
新增一個層,實現濾色器功能。
那本文到這裡就結束了,謝謝觀看,明天見~