废话不多说,先上本次要实现的效果图。
Gif格式是渣像素,实际效果要自然的多。这个项目其实是看到小池记账小程序后实现的一个类似效果,小池比较闪光的一点就是这个主界面的动态高斯模糊效果,不过小池的动态模糊效果就不如Flutter可以做的这么自然流畅了,模糊时还是有肉眼可见的卡顿的。大家可以搜索小池记账对比一下,下面进入正文。
知识点
- Flutter中如何截取当前屏幕的Widget图片。
- Flutter如何对一张图片进行高斯模糊。
- 如何淡入淡出切换两个Widget。
Flutter截取当前屏幕的Widget图片
- 目前官网文档还没有相关的例子,正式发布的Beta3版本也没有公开的方法,但事实上,在未公开发布的Flutter v0.4.4中,已经有截取当前屏幕Widget图片的文档了,地址在这里。我们需要切换到当前的开发分支才能看到这个新的方法
toImage()
。你可以直接在Flutter的本地git仓库checkout到master
分支,当然,也可以用下面更简单的方法,运行这两个命令,Flutter会自动切换到最新分支并下载依赖,到这里,准备工作就算完成了。
flutter channel master
flutter doctor -v
- 给需要截图的Widget包裹一个
RepaintBoundary
,如下示例代码:
class _PngHomeState extends State<PngHome> {
GlobalKey globalKey = new GlobalKey();
// 截图boundary,并且返回图片的二进制数据。
Future<Uint8List> _capturePng() async {
RenderRepaintBoundary boundary = globalKey.currentContext.findRenderObject();
ui.Image image = await boundary.toImage();
// 注意:png是压缩后格式,如果需要图片的原始像素数据,请使用rawRgba
ByteData byteData = await image.toByteData(format: ui.ImageByteFormat.png);
Uint8List pngBytes = byteData.buffer.asUint8List();
return pngBytes;
}
@override
Widget build(BuildContext context) {
return RepaintBoundary(
//globalKey用于识别
key: globalKey,
child: Center(
child: FlatButton(
child: Text('Hello World', textDirection: TextDirection.ltr),
onPressed: _capturePng,
),
),
);
}
目前这个方法还是挺费时间的,大概在100ms左右才能得到截图,更别说我们还要对图片做处理,所以,尽管我对生成的图片做了缓存,但是第一次得到图片的时候,还是会有一小会的停顿(200-300ms)
对得到的图片进行高斯模糊
拿到了图片的二进制数据,怎么对其进行高斯模糊?搜索官网发现了一个很好的库:image
,把它添加到项目中来,在pubspec.yaml
中添加如下代码:
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^0.1.0
image: "^1.1.32"
然后在项目中import,注意取一个别名,不要跟Flutter已有的Image
库冲突:
import