【问题标题】:Flutter Custompainter canvas drawimage not workingFlutter Custompainter画布drawimage不起作用
【发布时间】:2019-08-13 07:33:32
【问题描述】:

我尝试使用 Canvas 和 CustomPainter 绘制图像,但它不起作用。这是针对使用 Flutter Framework 的 Android 应用程序。

我刚刚在 Windows cmd 中使用命令 flutter build apk 来构建应用程序。

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;
  }
}

应用程序没有任何错误,但没有发生任何事情。这只是一个白屏。 我的代码有什么问题?

White screen of the builded app

【问题讨论】:

    标签: android canvas flutter dart


    【解决方案1】:

    正如@Muldec 所说,图像需要在画布上绘制之前可用。在这种情况下,FuturBuilder 是合适的。

    class _MyStatefulWidgetState extends State<MyStatefulWidget> {
      late Future<ui.Image> _image;
    
      @override
      void initState() {
        _image = _loadImage('path/image.jpg');
      }
    
      Future<ui.Image> _loadImage(String imagePath) async {
        ByteData bd = await rootBundle.load(imagePath);
        final Uint8List bytes = Uint8List.view(bd.buffer);
        final ui.Codec codec = await ui.instantiateImageCodec(bytes);
        final ui.Image image = (await codec.getNextFrame()).image;
    
        return image;
      }
    
      @override
      Widget build(BuildContext context) {
        return FutureBuilder<ui.Image>(
            future: _image,
            builder: (BuildContext context, AsyncSnapshot<ui.Image> snapshot) {
              Widget centerChild;
              if (snapshot.hasData) {
                centerChild =
                    CustomPaint(painter: ImageEditor(image: snapshot.data!));
              } else {
                centerChild = const CircularProgressIndicator();
              }
              return Scaffold(
                  appBar: AppBar(title: const Text('Title!')),
                  body: Center(child: centerChild));
            });
      }
    }
    
    class ImageEditor extends CustomPainter {
      final ui.Image image;
    
      ImageEditor({required this.image});
    
      @override
      Future paint(Canvas canvas, Size size) async {
        canvas.save();
    
        canvas.drawImage(image, Offset(0.0, 0.0), Paint());
    
        canvas.save();
        canvas.restore();
      }
    
      @override
      bool shouldRepaint(CustomPainter oldDelegate) => false;
    }
    
    

    【讨论】:

      【解决方案2】:

      您的图像需要在画布绘制之前可用。通过将加载代码移到画家之外,画家现在可以按预期工作:

      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;
        }
      }
      

      请注意,您可以使用Image.asset 而不是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'),
              ),
            ),
          );
        }
      

      【讨论】:

      • 太棒了!我试过这个并为我工作,但我面临一个问题是图像没有绘制到精确的偏移位置有什么想法吗?
      • 如果没有关于您的代码的更多信息,可能很难为您提供帮助。我建议您创建一个包含代码的完整详细信息的新帖子。然后,您还将获得知名度。
      • 感谢您的回复,但现在我解决了!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-06-15
      • 1970-01-01
      • 1970-01-01
      • 2019-11-05
      • 2020-08-29
      • 1970-01-01
      • 2012-03-22
      相关资源
      最近更新 更多