简体   繁体   English

如何将带有子图像小部件的小部件转换为 Flutter 中的图像文件?

[英]How to convert a widget with child Image widgets into an image file in Flutter?

I am using the RenderRepaintBoundary / GlobalKey technique to convert a Widget into an image file.我正在使用RenderRepaintBoundary / GlobalKey技术将 Widget 转换为图像文件。 The problem is that any child Image Widgets in the Widget disappear when I convert the Widget to an image file, but everything else on the screen, besides the child Image Widgets, makes it into the image file.问题是,当我将小部件转换为图像文件时,小部件中的任何子图像小部件都会消失,但屏幕上的所有其他内容,除了子图像小部件,都会将其放入图像文件中。

Here's my code.这是我的代码。 It's basically a screen with a button and an image on it.它基本上是一个带有按钮和图像的屏幕。 If you click the button then an image snapshot is taken of the Widget and then the app displays this snapshot and nothing else.如果您单击该按钮,则会拍摄 Widget 的图像快照,然后应用程序会显示此快照,而不会显示其他任何内容。 As a result, the child Image disappears.结果,子图像消失了。 There is a bit more explanation below this code:这段代码下面有更多解释:

import 'package:flutter/material.dart';
import 'dart:io';
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:path_provider/path_provider.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 Home Page'),
    );
  }
}

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

  final String? title;

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

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;
  Uint8List? ssBytes;
  bool isShowSs = false;

  final GlobalKey genKey = GlobalKey();

  Future<void> takePicture() async {
    RenderRepaintBoundary boundary = genKey.currentContext!.findRenderObject()! as RenderRepaintBoundary;
    ui.Image image = await boundary.toImage();
    ByteData? byteData = await image.toByteData(format: ui.ImageByteFormat.png);
    ssBytes = byteData!.buffer.asUint8List();
    setState(() {
      isShowSs = true;
    });
  }

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    if(isShowSs) {
      return Image.memory(ssBytes!);
    }
    else {
      return RepaintBoundary(
        key: genKey,
        child: Scaffold(
          appBar: AppBar(
            title: Text(widget.title!),
          ),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Text(
                  'You have pushed the button this many times:',
                ),
                Text(
                  '$_counter',
                  style: Theme.of(context).textTheme.headline4,
                ),
                ElevatedButton(
                    onPressed: () async {
                      await takePicture();
                    },
                    child: Text(
                      "Take Picture",
                    )),
                Image.asset('assets/images/img.png'),
              ],
            ),
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: _incrementCounter,
            tooltip: 'Increment',
            child: Icon(Icons.add),
          ),
        ),
      );
    }
  }
}

To clarify, this is the element that disappears from the image capture:为了澄清,这是从图像捕获中消失的元素:

Image.asset('assets/images/img.png')

How can I make it so that this sub-image appears in the image capture?我怎样才能使这个子图像出现在图像捕获中?

If you are on flutter web and using the html renderer instead of canvaskit, may this article explains the issue: https://github.com/flutter/flutter/issues/47721 It points out that on flutter web RenderRepaintBoundary.toImage() doesn't work for other images like the asset image due to cross-origin restrictions. If you are on flutter web and using the html renderer instead of canvaskit, may this article explains the issue: https://github.com/flutter/flutter/issues/47721 It points out that on flutter web RenderRepaintBoundary.toImage() doesn由于跨域限制,它不适用于资产图像等其他图像。

... In general on the Web it is hard to get the pixels of a web-page due to cross-origin restrictions. ... 一般来说,在 Web 上,由于跨域限制,很难获取网页的像素。 We can partially support it in the CanvasKit backend, but again, we won't be able to get the pixels of cross-origin images or platform views.我们可以在 CanvasKit 后端部分支持它,但同样,我们将无法获取跨域图像或平台视图的像素。 ... ...

In this case the solution would be to use the canvaskit renderer if possible.在这种情况下,解决方案是尽可能使用 canvaskit 渲染器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM