前言
继续上一篇 Flutter侧滑栏及城市选择UI的实现,今天继续讲Flutter的实现篇,画中画效果的实现。先看一下PIP的实现效果.
更多效果请查看PIP DEMO
代码地址:FlutterPIP
为什么会有此文?
一天在浏览朋友圈时,发现了一个朋友发了一张图(当然不是女朋友,但是个女的),类似上面效果部分. 一看效果挺牛啊,这是怎么实现的呢?心想要不自己实现一下吧?于是开始准备用Android实现一下.
但最近正好学了一下Flutter,并在学习Flutter 自定义View CustomPainter时,发现了和Android上有相同的API,Canvas,Paint,Path等. 查看Canvas的绘图部分drawImage代码如下
/// Draws the given [Image] into the canvas with its top-left corner at the
/// given [Offset]. The image is composited into the canvas using the given [Paint].
void drawImage(Image image, Offset p, Paint paint) {
assert(image != null); // image is checked on the engine side
assert(_offsetIsValid(p));
assert(paint != null);
_drawImage(image, p.dx, p.dy, paint._objects, paint._data);
}
void _drawImage(Image image,
double x,
double y,
List<dynamic> paintObjects,
ByteData paintData) native 'Canvas_drawImage';
可以看出drawImage 调用了内部的_drawImage,而内部的_drawImage使用的是native Flutter Engine的代码 ‘Canvas_drawImage’,交给了Flutter Native去绘制.那Canvas的绘图就可以和移动端的Native一样高效 (Flutter的绘制原理,决定了Flutter的高效性).关于Flutter的高效可以查看 Flutter 高性能原理
实现步骤
看效果从底层往上层,图片被分为3个部分,第一部分是底层的高斯模糊效果,第二层是原图被裁剪的部分,第三层是一个效果遮罩。
Flutter 高斯模糊效果的实现
Flutter提供了BackdropFilter,关于BackdropFilter的官方文档是这么说的
A widget that applies a filter to the existing painted content and then paints child.
The filter will be applied to all the area within its parent or ancestor widget’s clip. If there’s no clip, the filter will be applied to the full screen.
简单来说,他就是一个筛选器,筛选所有绘制到子内容的小控件,官方demo例子如下
Stack(
fit: StackFit.expand,
children: <Widget>[
Text('0' * 10000),
Center(
child: ClipRect( // <-- clips to the 200x200 [Container] b