Flutter之RepaintBoundary组件

https://www.jianshu.com/p/6801ecbee03d

/**
 * const RepaintBoundary({ Key key, Widget child })
 */

//import ‘dart:io‘;
//import ‘dart:typed_data‘;
//import ‘package:flutter/material.dart‘;
//import ‘package:flutter/rendering.dart‘;
//import ‘dart:ui‘;
//import ‘package:path_provider/path_provider.dart‘;

class Widget_RepaintBoundary_State extends State<Widget_RepaintBoundary_Page> {
  GlobalKey globalKey = new GlobalKey();

  Future<File> _capture() async {
    try {
      RenderRepaintBoundary boundary = globalKey.currentContext
          .findRenderObject();
      //boundary.toImage()转化为ui.Image对象,不会自动为包裹的组件添加背景,不设置可能会缺失背景
      var image = await boundary.toImage(pixelRatio: window.devicePixelRatio);
      //将image转化为byteData
      ByteData byteData = await image.toByteData(format: ImageByteFormat.png);
      //这个对象就是图片数据
      Uint8List pngBytes = byteData.buffer.asUint8List();

      String sTempDir = (await getTemporaryDirectory()).path;
      bool isDirExist = await Directory(sTempDir).exists();
      if (!isDirExist) {
        Directory(sTempDir).create();
      }

      Future<File> file = File(sTempDir + "/abc.png").writeAsBytes(pngBytes);

      return file;

    } catch (e) {
      print(e);
    }
    return null;
  }

  @override
  Widget build(BuildContext context) {
    var file = "/data/user/0/com.yourcompany.test1/cache/abc.png";
    return MaterialApp(
      home: Scaffold(
          appBar: AppBar(
            title: Text("RepaintBoundary"),
          ),
          body: Column(
            children: <Widget>[
              RepaintBoundary(
                key: globalKey,
                child: Text("RepaintBoundary组件"),
              ),
              RaisedButton(
                  onPressed: () {
                    _capture().then((_file){
                      setState(() {
                        debugPrint(_file.path);
                        file = _file.path;
                      });
                    }).whenComplete((){

                    });
                  }
              ),
              Image.asset(file),
            ],
          )
      ),
    );
  }
}

作者:习惯了_就好
链接:https://www.jianshu.com/p/6801ecbee03d
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

如何截图

前面说到本篇会用到RepaintBoundary组件,接下来把它套在你想要截图的组件的外层,想截全屏的话就套在最外面就可以,Flutter的这种写法习惯就好。
同时定义一个Key用来操作这个组件

class _MyHomePageState extends State<MyHomePage> {
  GlobalKey rootWidgetKey = GlobalKey();
  ...

  @override
  Widget build(BuildContext context) {
    return RepaintBoundary(
      key: rootWidgetKey,
      child: Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body: Column(
          .....
        ),
      ),
    );
  }
}

通过rootWidgetKey可以拿到RenderRepaintBoundary的引用,进来拿到内部组件的截图:

class _MyHomePageState extends State<MyHomePage> {
  GlobalKey rootWidgetKey = GlobalKey();

  Future<Uint8List> _capturePng() async {
    try {
      RenderRepaintBoundary boundary =
          rootWidgetKey.currentContext.findRenderObject();
      var image = await boundary.toImage(pixelRatio: 3.0);
      ByteData byteData = await image.toByteData(format: ImageByteFormat.png);
      Uint8List pngBytes = byteData.buffer.asUint8List();
      return pngBytes;//这个对象就是图片数据
    } catch (e) {
      print(e);
    }
    return null;
  }
  ...
}

通过上面一系列的方法调用,就拿到了一个Unit8List类型的图片数据。

显示截图

而Unit8List类型的图片数据的显示也非常简单,通过Image.memory方法从内存中加载图片,下面附上完整的State代码:

class _MyHomePageState extends State<MyHomePage> {
  GlobalKey rootWidgetKey = GlobalKey();

  List<Uint8List> images = List();

  _capturePng() async {
    try {
      RenderRepaintBoundary boundary =
          rootWidgetKey.currentContext.findRenderObject();
      var image = await boundary.toImage(pixelRatio: 3.0);
      ByteData byteData = await image.toByteData(format: ImageByteFormat.png);
      Uint8List pngBytes = byteData.buffer.asUint8List();
      images.add(pngBytes);
      setState(() {});
      return pngBytes;
    } catch (e) {
      print(e);
    }
    return null;
  }

  @override
  Widget build(BuildContext context) {
    return RepaintBoundary(
      key: rootWidgetKey,
      child: Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body: Column(
          children: <Widget>[
            Image.network(
              "http://qiniu.nightfarmer.top/test.gif",
              width: 300,
              height: 300,
            ),
            FlatButton(
              onPressed: () {
                this._capturePng();
              },
              child: Text("全屏截图"),
            ),
            Expanded(
              child: ListView.builder(
                itemBuilder: (context, index) {
                  return Image.memory(
                    images[index],
                    fit: BoxFit.cover,
                  );
                },
                itemCount: images.length,
                scrollDirection: Axis.horizontal,
              ),
            )
          ],
        ),
      ),
    );
  }
}

作者:NightFarmer
链接:https://www.jianshu.com/p/da3f23d0843b
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

原文地址:https://www.cnblogs.com/sundaysme/p/12706793.html

时间: 04-15

Flutter之RepaintBoundary组件的相关文章

Flutter 开发之组件一

Flutter 的口号:一切谐为组件.同其他平台一样,Flutter 提供了一系列的组件,有基础组件(Basics Widgets),质感组件(Material Components).Cupertino 等. Flutter 中基础组件的介绍,用法也比较简单.每个组件都是一个以类的形式存在.Flutter 的组件属性也很多,我们不可能记得每一项,只有经常使用或者了解一些关键属性,然后用到时再去查看具体属性.正所谓“流水的属性,铁打的组件”. Flutter的UI控件的使用方法 Flutter

Flutter之ExpansionTile组件

ExpansionTile组件 ExpansionTile Widget就是一个可以展开闭合的组件,常用的属性有如下几个. title:闭合时显示的标题,这个部分经常使用Text Widget. leading:标题左侧图标,多是用来修饰,让界面显得美观. backgroundColor: 展开时的背景颜色,当然也是有过度动画的,效果非常好. children: 子元素,是一个数组,可以放入多个元素. trailing : 右侧的箭头,你可以自行替换但是我觉的很少替换,因为谷歌已经表现的很完美了

Flutter 布局类组件:流式布局(Wrap和Flow)

前言 把超出屏幕显示范围会自动折行的布局称为流式布局.Flutter中通过Wrap和Flow来支持流式布局,将Row换成Wrap后溢出部分则会自动折行. Wrap 接口描述 Wrap({ Key key, this.direction = Axis.horizontal, this.alignment = WrapAlignment.start, // 主轴方向子widget的间距 this.spacing = 0.0, // 纵轴方向的对齐方式 this.runAlignment = Wrap

调用 flutter 第三方时间组件

https://pub.flutter-io.cn/packages/flutter_cupertino_date_picker flutter_cupertino_date_picker: ^1.0.12 import 'package:flutter/material.dart';import 'package:flutter_cupertino_date_picker/flutter_cupertino_date_picker.dart'; class DatePage extends S

Flutter 布局类组件

Column 类似Android里的LinearLayout里的Vertical 竖直布局 Row 类似 Android里的LinearLayout里的horizontal 水平布局 Flex 自适应布局,可以使用flex属性 规定子布局所占比大小,也可用direction规定方向 还有流式布局Warp,可以在子控件超出屏幕范围后自动换行,而Row是不可以的 Stack于Android中的FrameLayout类似,后置入的子控件将会显示在最上面 Center 居中显示布局,内部子控件会居中显示

Flutter 开发集合系列之优雅的 Flutter 组件化 混编方案大神必学

背景 此篇文章,主要针对想要在原有Native工程的基础上集成Flutter的需求,所提供的混编方案的探讨. 官方方案的优缺点 (1)优点: 不需要每次 Run 起来之后,先进行 同步flutter代码(组件化Flutter后,因为组件化后flutter代码已经变为framework,所以每次进来需要先热更新同步代码)不需要单独搞一个组件进行集成,管理组件的版本,发布等.(2)缺点: 会非常耦合工程,需要修改工程配置,添加 BUILD PHASE 调用 flutter 中 xcode_backe

Flutter StatefulWidget 有状态组件、页面上绑定数据、改变页面数据

在 Flutter 中自定义组件其实就是一个类,这个类需要继承 StatelessWidget/StatefulWidget. StatelessWidget 是无状态组件,状态不可变的 widget StatefulWidget 是有状态组件,持有的状态可能在 widget 生命周期改变.通俗的讲:如果我 们想改变页面中的数据的话这个时候就需要用到 StatefulWidget import 'package:flutter/material.dart'; void main() => run

Flutter 不一样的跨平台解决方案

本文主要介绍Flutter相关的东西,包括Fuchsia.Dart.Flutter特性.安装以及整体架构等内容. 1. 简介 Flutter作为谷歌最近推出的跨平台开发框架,一经推出便吸引了不少注意.关于Flutter,目前我们知道它是一个跨平台开发框架.但是它本身并不止于此,例如Fuchsia.Dart等,我们也都需要去了解. 1.1 Fuchsia 说到Flutter,绝对绕不开Fuchsia,这个是谷歌开发的一款全新的操作系统,GitHub地址以及Google source主页.Fuchs

UI2Code智能生成Flutter代码--整体设计篇

背景:??随着移动互联网时代的到来,人类的科学技术突飞猛进.然而软件工程师们依旧需要花费大量精力在重复的还原UI视觉稿的工作.UI视觉研发拥有明显的特征:组件,位置和布局,符合机器学习处理范畴.能否通过机器视觉和深度学习等手段自动生成UI界面代码,来解放重复劳动力,成为我们关注的方向. UI2CODE简单介绍:??UI2CODE项目是闲鱼技术团队研发的一款通过机器视觉理解+AI人工智能将UI视觉图片转化为端侧代码的工具. ??2018年3月UI2CODE开始启动技术可行性预研工作,到目前为止,经