Flutter之RepaintBoundary组件

chaoxiao 2020-04-15

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
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
 
 
 
 
 

相关推荐