如何从Custom Paint保存图像?

时间:2020-04-23 14:42:25

标签: flutter

我正在尝试制作一个简单的应用程序,该应用程序根据用户的输入进行绘制。使基本功能,我遇到了问题,我无法保存图像。我搜索了一下,发现我应该使用PictureRecorder(),但是我无法使其工作(我的错不是错误)。所以我想问你如何实现PictureRecorder并使用Custom Paint将图像保存到磁盘。

这是代码:

import 'package:flutter/services.dart';
import 'dart:ui' as ui;

class Painter extends StatefulWidget {
  static String id = 'Painter';
  @override
  _PainterState createState() => _PainterState();
}

class _PainterState extends State<Painter> {
  final recorder = new ui.PictureRecorder();
  double canvasWidth = 1200;
  double canvasHeight = 1000;
  double SecondWidth = 0;
  double SecondHeight = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.blueGrey,
      appBar: AppBar(
        title: Center(
          child: Text(
            '⚡  ⚡',
            style: TextStyle(color: Colors.blue),
          ),
        ),
        backgroundColor: Colors.black26,
      ),
      body: SafeArea(
        child: Container(
          padding: EdgeInsets.all(10.0),
          child: ListView(
            children: <Widget>[
              Column(
                crossAxisAlignment: CrossAxisAlignment.center,
                children: <Widget>[
                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: <Widget>[
                      Text('⚡  ⚡'),
                      SizedBox(
                        width: 150.0,
                        child: TextField(
                          decoration: InputDecoration(
                              border: InputBorder.none, hintText: 'title'),
                        ),
                      ),
                    ],
                  ),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: <Widget>[
                      Text('Canvas  Height'),
                      SizedBox(
                        width: 150.0,
                        child: TextField(
                          onChanged: (value) {
                            setState(() {
                              canvasHeight = double.parse(value);
                            });
                          },
                          decoration: InputDecoration(
                              border: InputBorder.none,
                              hintText: 'Canvas. Height'),
                          inputFormatters: [
                            WhitelistingTextInputFormatter.digitsOnly
                          ],
                          keyboardType: TextInputType.number,
                        ),
                      ),
                    ],
                  ),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: <Widget>[
                      Text('Canvas. Width'),
                      SizedBox(
                        width: 150.0,
                        child: TextField(
                          onChanged: (value) {
                            setState(() {
                              canvasWidth = double.parse(value);
                            });
                            print(canvasWidth);
                          },
                          decoration: InputDecoration(
                              border: InputBorder.none,
                              hintText: 'Canvas. Width'),
                          inputFormatters: [
                            WhitelistingTextInputFormatter.digitsOnly
                          ],
                          keyboardType: TextInputType.number,
                        ),
                      ),
                    ],
                  ),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: <Widget>[
                      Text('Second. height'),
                      SizedBox(
                        width: 150.0,
                        child: TextField(
                          decoration: InputDecoration(
                              border: InputBorder.none,
                              hintText: 'Second. height'),
                          inputFormatters: [
                            WhitelistingTextInputFormatter.digitsOnly
                          ],
                          keyboardType: TextInputType.number,
                          onChanged: (value) {
                            setState(() {
                              SecondHeight = double.parse(value);
                            });
                          },
                        ),
                      ),
                    ],
                  ),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: <Widget>[
                      Text('Secon. width'),
                      SizedBox(
                        width: 150.0,
                        child: TextField(
                          decoration: InputDecoration(
                              border: InputBorder.none,
                              hintText: 'Second. Width'),
                          inputFormatters: [
                            WhitelistingTextInputFormatter.digitsOnly
                          ],
                          keyboardType: TextInputType.number,
                          onChanged: (value) {
                            setState(() {
                              SecondWidth = double.parse(value);
                            });
                          },
                        ),
                      ),
                    ],
                  ),
                ],
              ),
              RaisedButton(
                onPressed: () async {
                  final picture = recorder.endRecording();
                  final img = picture.toImage(200, 200);
                  final pngBytes = await img.toByteData(format: new ui.EncodingFormat.png());
                },
                child: Text('Save Image'),
              ),
              FittedBox(
                child: SizedBox(
                  width: canvasWidth,
                  height: canvasHeight,
                  child: Container(
                    color: Colors.yellow,
                    child: CustomPaint(
                      painter: BoxInABox(
                        canvasrecorder: recorder,
                        width: canvasWidth,
                        height: canvasHeight,
                        iHeight: SecondHeight,
                        iWidth: SecondWidth,
                      ),
                    ),
                  ),
                ),
              )
            ],
          ),
        ),
      ),
    );
  }
}

class BoxInABox extends CustomPainter {
  @override
  BoxInABox({this.width, this.height, this.iWidth, this.iHeight, this.canvasrecorder});

  final double width;
  final double height;
  final double iWidth;
  final double iHeight;
  final canvasrecorder;

  void paint(Canvas canvas, Size size) {
    final paint = Paint()
      ..style = PaintingStyle.stroke
      ..strokeWidth = 4.0
      ..color = Colors.indigo;

    canvas.drawRect(
        Rect.fromCenter(
          height: height,
          width: width,
          center: Offset(
            width / 2,
            height / 2,
          ),
        ),
        Paint()..color = Colors.green);

    canvas.drawRect(
        Rect.fromCenter(
          height: iHeight,
          width: iWidth,
          center: Offset(
            width / 2,
            height / 2,
          ),
        ),
        Paint()..color = Colors.red);
  }

  @override
  bool shouldRepaint(BoxInABox oldDelegate) => true;
}

预先感谢

编辑:更新了代码,包括我未能实现记录器的尝试,P.s给我一个关于“错误:

的错误信息

未为类“ Future”定义方法“ toByteData”。 (位于[flutterappquesion] lib \ main.dart:152的undefined_method)'和 错误:未定义的类'ui.EncodingFormat'。 (undefined_class位于 [flutterappquesion] lib \ main.dart:152)

2 个答案:

答案 0 :(得分:2)

只需在PictureRecorder上使用Canvas

PictureRecorder pictureRecorder = PictureRecorder();
Canvas canvas = Canvas(pictureRecorder);

// Paint your canvas as you want

Picture picture = pictureRecorder.endRecording();
Image image = await picture.toImage(yourWidth, yourHeight);

答案 1 :(得分:0)

或者,您通过RepaintBoundary小部件将特定的小部件另存为图像:screenshot