
BackdropFilter 组件可能很少人使用,但它的功能还是很强大的。源码中对它的介绍是:对已有的绘制内容添加一个过滤器,然后再绘制它的孩子。

下面是 BackdropFilter 组件类的定义和 构造方法,可以看出它继承自 SingleChildRenderObjectWidget 。构造时必须传入尺寸 filter 参数,其类型是 ImageFilter。

final ui.ImageFilter filter;源码中有一个 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(),
),首先 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),
),
),
);
}BackdropFilter 继承自 SingleChildRenderObjectWidget ,内部维护 RenderBackdropFilter 渲染对象来实现添加滤色器功能。

在 RenderBackdropFilter#paint 中创建 BackdropFilterLayer 对象 layer,并将传入的 filter 设置给 layer 。通过 context.pushLayer 添加一个层,实现滤色器功能。

那本文到这里就结束了,谢谢观看,明天见~