Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flutter Custompainter canvas drawimage not working

I tried to draw image using Canvas and CustomPainter but it's not working. This is for an Android app using Flutter Framework.

I just used command flutter build apk in Windows cmd to build the app.

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: AppBar(title: Text('Title!')),
      body: Center(
        child: AspectRatio(
          aspectRatio: 1.0,
          child: CustomPaint(
            painter: ImageEditor(),
          ),
        ),
      ),
    );
  }
}

class ImageEditor extends CustomPainter {
  @override
  Future paint(Canvas canvas, Size size) async {
    canvas.save();

    ByteData bd = await rootBundle.load("assets/sampleImagees.jpg");

    final Uint8List bytes = Uint8List.view(bd.buffer);

    final ui.Codec codec = await ui.instantiateImageCodec(bytes);

    final ui.Image image = (await codec.getNextFrame()).image;

    canvas.drawImage(image, Offset(0.0, 0.0), Paint());

    canvas.save();
    canvas.restore();
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return false;
  }
}

There isn't any error but nothing happend in the app. It's just a white screen. What's wrong in my code?

White screen of the builded app

like image 712
Goldenbough Avatar asked Aug 13 '19 07:08

Goldenbough


1 Answers

Your image needs to be available before the canvas is drawn. By moving the loading code outside of the painter, the painter now works as intended :

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  ui.Image _image;

  @override
  void initState() {
    _loadImage();
  }

  _loadImage() async {
    ByteData bd = await rootBundle.load("assets/sampleImagees.jpg");

    final Uint8List bytes = Uint8List.view(bd.buffer);

    final ui.Codec codec = await ui.instantiateImageCodec(bytes);

    final ui.Image image = (await codec.getNextFrame()).image;

    setState(() => _image = image);
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: AppBar(title: Text('Title!')),
      body: Center(
        child: AspectRatio(
          aspectRatio: 1.0,
          child: CustomPaint(
                painter: ImageEditor(_image),
              )
        ),
      ),
    );
  }
}

class ImageEditor extends CustomPainter {
  ui.Image image;

  ImageEditor(this.image) : super();

  @override
  Future paint(Canvas canvas, Size size) async {
    if (image != null) {
      canvas.drawImage(image, Offset(0.0, 0.0), Paint());
    }
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return image != (oldDelegate as ImageEditor).image;
  }
}

Note that you can easily draw an image using Image.asset instead of a CustomPainter :

  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: AppBar(title: Text('Title!')),
      body: Center(
        child: AspectRatio(
          aspectRatio: 1.0,
          child: Image.asset('assets/sampleImagees.jpg'),
        ),
      ),
    );
  }
like image 122
Muldec Avatar answered Sep 22 '22 12:09

Muldec