Flutter之屏幕截图/组件截图

栏目: ASP.NET · 发布时间: 6年前

内容简介:继续更新Flutter系列,本篇记录如何在Flutter中进行截图,在Flutter中万物皆组件,不但高斯模糊是套一层组件,截图也是套一层组件,所以屏幕截图和组件截图其实是一个意思。虽然Flutter的这种嵌套UI很繁琐,但是用习惯了反而会感觉结构很清晰,不用担心布局相关代码的混乱,在FlutterInspector识图下更是一目了然,可以在不翻阅代码的情况下快速理解别人写的布局。本次用到的组件是RepaintBoundary,效果图:依照惯例,创建一个简单的Flutter工程,清理main.dart中无

继续更新Flutter系列,本篇记录如何在Flutter中进行截图,在Flutter中万物皆组件,不但高斯模糊是套一层组件,截图也是套一层组件,所以屏幕截图和组件截图其实是一个意思。虽然Flutter的这种嵌套UI很繁琐,但是用习惯了反而会感觉结构很清晰,不用担心布局相关代码的混乱,在FlutterInspector识图下更是一目了然,可以在不翻阅代码的情况下快速理解别人写的布局。

本次用到的组件是RepaintBoundary,效果图:

Flutter之屏幕截图/组件截图

创建Flutter工程

依照惯例,创建一个简单的Flutter工程,清理main.dart中无用的代码便于演示:

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Column(),
    );
  }
}

复制代码

这就是一个带有标题栏的空界面。

写一个简单的场景

便于演示,在这个界面中加入一个gif图片,当然你用普通图片或者视频也是可以的:

class _MyHomePageState extends State<MyHomePage> {
  Future<Uint8List> _capturePng() async {
    //TODO 进行截图
  }
  
  @override
  Widget build(BuildContext context) {
    return 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("全屏截图"),
          ),
        ],
      ),
    );
  }
}
复制代码

加入图片之后我顺便加入了一个FlatButton组件,通过这个点击这个按钮来触发截图的逻辑。

当然到目前为止这还是只是一个简单的界面布局,没有用到任何新的东西。

如何截图

前面说到本篇会用到 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,
              ),
            )
          ],
        ),
      ),
    );
  }
}

复制代码

完工。

更多干货移步我的个人博客www.nightfarmer.top/


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Perl入门经典

Perl入门经典

[美]Curtis "Ovid" Poe / 朱允刚、韩雷、叶斌 / 清华大学出版社 / 2013-9-20 / 78.00

作为最有影响力的编程语言之一,Perl被广泛用在Web开发、数据处理和系统管理中。无论是Perl新手,还是想要加强自己实战技能的Perl程序员,《Perl入门经典》都提供了处理日常情况所需的各种技术。凭借十多年的Perl经验,作者Curtis“Ovid”Poe一开始先简单回顾了Perl的基础知识,然后以此为出发点,举例说明了Perl在工作场所中的各种真实用法。此外,书中还包含了一些动手练习、宝贵建......一起来看看 《Perl入门经典》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试