繁体   English   中英

如何在颤动中从 CustomPainter 获取 png

[英]How to get get png from CustomPainter in flutter

我认为这个问题很清楚,但是我想要使用画布在屏幕上绘制的图案中的 png,我该怎么做,这是我的代码..我已经尝试了一切 目前由于时间限制,我正在使用 RepaintBoundary完整堆栈的屏幕截图,但是我需要更好的功能..任何指针?...我已经尝试寻找,但目前还没有找到任何解决方案。我正在研究一种需要用户签名的签名板并将其作为 png 在线发布,我可以让用户在屏幕上绘制并截取整个堆栈的屏幕截图,但无法仅从绘制的图案中获取 Png

class SignaturePainter extends CustomPainter {
  Paint _paint;
  SignaturePainter(this.points, this._paint);
  final List<Offset> points;
  List<Offset> offsetPoints = List();
  void paint(Canvas canvas, Size size) {
    for (int i = 0; i < points.length - 1; i++) {
      if (points[i] != null && points[i + 1] != null)
        canvas.drawLine(points[i], points[i + 1], _paint);
      if (points[i] != null && points[i + 1] == null) {
        offsetPoints.clear();
        offsetPoints.add(points[i]);
        offsetPoints.add(Offset(points[i].dx + 0.1, points[i].dy + 0.1));
        canvas.drawPoints(ui.PointMode.points, offsetPoints, _paint);
      }
    }
  }

  bool shouldRepaint(SignaturePainter other) => other.points != points;
}

class Signature extends StatefulWidget {
  SignatureState createState() => new SignatureState();
}

class SignatureState extends State<Signature> implements ClearScreen {
  List<Offset> _points = <Offset>[];
  Paint backgroundPaint, foregroundPaint;
  GlobalKey globalKey = GlobalKey();
  @override
  void initState() {
    backgroundPaint = new Paint()
      ..color = Colors.white
      ..strokeCap = StrokeCap.round
      ..strokeWidth = 5.0;
    foregroundPaint = new Paint()
      ..color = Colors.amber
      ..strokeCap = StrokeCap.round
      ..strokeWidth = 5.0;

    super.initState();
  }

  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        decoration: appGradient,
        height: MediaQuery.of(context).size.height,
        width: MediaQuery.of(context).size.width,
        child: RepaintBoundary(
          key: globalKey,
          child: Stack(
            children: [
              GestureDetector(
                onPanUpdate: (DragUpdateDetails details) {
                  RenderBox referenceBox = context.findRenderObject();
                  Offset localPosition =
                      referenceBox.globalToLocal(details.globalPosition);
                  setState(() {
                    _points = new List.from(_points)..add(localPosition);
                  });
                },
                onPanEnd: (DragEndDetails details) => _points.add(null),
                onPanStart: (details) {
                  setState(() {
                    RenderBox referenceBox = context.findRenderObject();
                    Offset localPosition =
                        referenceBox.globalToLocal(details.globalPosition);
                    _points = List.from(_points)..add(localPosition);
                  });
                },
              ),
              CustomPaint(
                painter: SignaturePainter(_points, backgroundPaint),
              ),
              Positioned(
                bottom: 0.0,
                child: Container(
                  width: MediaQuery.of(context).size.width,
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                    children: <Widget>[
                      Row(
                        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                        children: <Widget>[
                          Button("Proceed", Alignment.bottomLeft, this, 0),
                          Button("Redo", Alignment.bottomRight, this, 1),
                        ],
                      ),
                    ],
                  ),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }

  @override
  void clearScreen() {
    setState(() {
      _points.clear();
    });
  }

  @override
  void performProceedTapAction() async {
    RenderRepaintBoundary boundary =
        globalKey.currentContext.findRenderObject();
    ui.Image image = await boundary.toImage();
    ByteData byteData = await image.toByteData(format: ui.ImageByteFormat.png);
    Uint8List pngBytes = byteData.buffer.asUint8List();
    var extern = await getExternalStorageDirectory();
    String path = extern.path;
    int random = Random(10000).nextInt(1000000);
    File file = new File("$path/image-$random.png");
    await file.writeAsBytes(pngBytes).then((onValue) {
      print(onValue);
    });
  }
}

abstract class ClearScreen {
  void clearScreen();
  void performProceedTapAction();
}

class Button extends StatelessWidget {
  final String buttonText;
  final Alignment alignment;
  final ClearScreen mListener;
  final flag;
  const Button(this.buttonText, this.alignment, this.mListener, this.flag);
  @override
  Widget build(BuildContext context) {
    return Align(
      alignment: alignment,
      child: Container(
        height: 60,
        width: MediaQuery.of(context).size.width / 2,
        child: Card(
          elevation: 10,
          color: Color.fromARGB(255, 149, 208, 158),
          shape:
              RoundedRectangleBorder(borderRadius: BorderRadius.circular(30)),
          child: InkWell(
            onTap: () {
              if (flag == 1) {
                mListener.clearScreen();
              } else if (flag == 0) {
                mListener.performProceedTapAction();
              }
            },
            child: Center(
                child: Text(
              buttonText,
              style: TextStyle(
                  color: Colors.white,
                  fontWeight: FontWeight.w300,
                  fontSize: 20),
            )),
          ),
        ),
      ),
    );
  }
}

感谢@pskink 的指导,这里是解决错误的方法,我将完整的代码发布给其他人使用

class SignaturePainter extends CustomPainter {
  Paint _paint;
  SignaturePainter(this.points, this._paint);
  final List<Offset> points;
  List<Offset> offsetPoints = List();

  void paint(Canvas canvas, Size size) {
    for (int i = 0; i < points.length - 1; i++) {
      if (points[i] != null && points[i + 1] != null)
        canvas.drawLine(points[i], points[i + 1], _paint);
      if (points[i] != null && points[i + 1] == null) {
        offsetPoints.clear();
        offsetPoints.add(points[i]);
        offsetPoints.add(Offset(points[i].dx + 0.1, points[i].dy + 0.1));
        canvas.drawPoints(ui.PointMode.points, offsetPoints, _paint);
      }
    }
  }

  bool shouldRepaint(SignaturePainter other) => other.points != points;
}

class Signature extends StatefulWidget {
  SignatureState createState() => new SignatureState();
}

class SignatureState extends State<Signature> implements ClearScreen {
  List<Offset> _points = <Offset>[];
  Paint backgroundPaint, foregroundPaint;
  GlobalKey globalKey = GlobalKey();
  SignaturePainter signaturePainter;

  @override
  void initState() {
    backgroundPaint = new Paint()
      ..color = Colors.white
      ..strokeCap = StrokeCap.round
      ..strokeWidth = 5.0;

    super.initState();
  }

  Widget build(BuildContext context) {
    signaturePainter = SignaturePainter(_points, backgroundPaint);
    return Scaffold(
      body: Container(
        decoration: appGradient,
        height: MediaQuery.of(context).size.height,
        width: MediaQuery.of(context).size.width,
        child: Stack(
          children: [
            GestureDetector(
              onPanUpdate: (DragUpdateDetails details) {
                RenderBox referenceBox = context.findRenderObject();
                Offset localPosition =
                    referenceBox.globalToLocal(details.globalPosition);
                setState(() {
                  _points = new List.from(_points)..add(localPosition);
                });
              },
              onPanEnd: (DragEndDetails details) => _points.add(null),
              onPanStart: (details) {
                setState(() {
                  RenderBox referenceBox = context.findRenderObject();
                  Offset localPosition =
                      referenceBox.globalToLocal(details.globalPosition);
                  _points = List.from(_points)..add(localPosition);
                });
              },
            ),
            CustomPaint(
              painter: signaturePainter,
            ),
            Positioned(
              bottom: 0.0,
              child: Container(
                width: MediaQuery.of(context).size.width,
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  children: <Widget>[
                    Row(
                      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                      children: <Widget>[
                        Button("Proceed", Alignment.bottomLeft, this, 0),
                        Button("Redo", Alignment.bottomRight, this, 1),
                      ],
                    ),
                  ],
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }

  @override
  void clearScreen() {
    setState(() {
      _points.clear();
    });
  }

  @override
  void performProceedTapAction() async {
    ui.PictureRecorder recorder = ui.PictureRecorder();
    Canvas canvas = new Canvas(recorder);
    try {
      signaturePainter.paint(canvas, Size.infinite);
      print(canvas.hashCode);
      ui.Picture p = recorder.endRecording();
      ui.Image image = await p.toImage(
          MediaQuery.of(context).size.width.toInt(),
          MediaQuery.of(context).size.height.toInt());
      ByteData byteData =
          await image.toByteData(format: ui.ImageByteFormat.png);
      print(byteData.buffer.asUint8List());
      var external = await getExternalStorageDirectory();
      String path = external.path;
      File file =
          new File("$path/image-${DateTime.now().millisecondsSinceEpoch}.png");
      await file.writeAsBytes(byteData.buffer.asUint8List()).then((onValue) {
        print(onValue);
      });
    } catch (exception) {
      print(canvas.hashCode);
      print("Exception Thrown $exception");

      Fluttertoast.showToast(
          msg: "Something went wrong,try resubmitting",
          toastLength: Toast.LENGTH_SHORT,
          gravity: ToastGravity.CENTER,
          timeInSecForIos: 1,
          backgroundColor: Colors.blueGrey.shade500,
          textColor: Colors.white,
          fontSize: 16.0);
      setState(() {});
    }
  }

  @override
  void dispose() {
    super.dispose();
  }
}

abstract class ClearScreen {
  void clearScreen();
  void performProceedTapAction();
}

class Button extends StatelessWidget {
  final String buttonText;
  final Alignment alignment;
  final ClearScreen mListener;
  final flag;
  const Button(this.buttonText, this.alignment, this.mListener, this.flag);
  @override
  Widget build(BuildContext context) {
    return Align(
      alignment: alignment,
      child: Container(
        height: 60,
        width: MediaQuery.of(context).size.width / 2,
        child: Card(
          elevation: 10,
          color: Color.fromARGB(255, 149, 208, 158),
          shape:
              RoundedRectangleBorder(borderRadius: BorderRadius.circular(30)),
          child: InkWell(
            onTap: () {
              if (flag == 1) {
                mListener.clearScreen();
              } else if (flag == 0) {
                mListener.performProceedTapAction();
              }
            },
            child: Center(
                child: Text(
              buttonText,
              style: TextStyle(
                  color: Colors.white,
                  fontWeight: FontWeight.w300,
                  fontSize: 20),
            )),
          ),
        ),
      ),
    );
  }
}

暂无
暂无

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

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