前言:
这是我参与8月更文挑战的第 28 天,活动详情查看:8月更文挑战。为应掘金的八月更文挑战
,我准备在本月挑选 31
个以前没有介绍过的组件,进行全面分析和属性介绍。这些文章将来会作为 Flutter 组件集录
的重要素材。希望可以坚持下去,你的支持将是我最大的动力~
| 本系列 | 组件文章 | 列表 | | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | | 1.NotificationListener | 2.Dismissible | 3.Switch | | 4.Scrollbar | 5.ClipPath | 6.CupertinoActivityIndicator | | 7.Opacity | 8.FadeTransition | 9. AnimatedOpacity | | 10. FadeInImage | 11. Offstage | 12. TickerMode | | 13. Visibility | 14. Padding | 15. AnimatedContainer | | 16.CircleAvatar | 17.PhysicalShape | 18.Divider | | 19.Flexible、Expanded 和 Spacer | 20.Card | 21.SizedBox | | 22.ConstrainedBox | 23.Stack | 24.Positioned | | 25.OverflowBox | 26.SizedOverflowBox | 27. DecoratedBox | | 28. BackdropFilter | | |
1.认识 BackdropFilter 组件
BackdropFilter
组件可能很少人使用,但它的功能还是很强大的。源码中对它的介绍是:对已有的绘制内容添加一个过滤器,然后再绘制它的孩子。
下面是 BackdropFilter
组件类的定义
和 构造方法
,可以看出它继承自 SingleChildRenderObjectWidget
。构造时必须传入尺寸 filter
参数,其类型是 ImageFilter
。
dart final ui.ImageFilter filter;
2.BackdropFilter 的使用
源码中有一个 BackdropFilter
组件的测试案例,我们先基于这个案例,看一下 BackdropFilter
的效果及作用。下图中,有三个区域: 01文字
、紫色区域
、Hello World
文字。实现的方式是:通过 Stack
叠合 01文字
和 BackdropFilter
,其中紫色区域和Hello World
文字是 BackdropFilter
的子组件。
```dart 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
等裁剪组件进行裁剪,这样模糊层
就不会影响之外的部分。如下是圆角矩形的裁剪效果:
dart 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
。
dart 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
添加一个层,实现滤色器功能。
那本文到这里就结束了,谢谢观看,明天见~