【问题标题】:Flutter Canvas Not Repainting颤振画布不重绘
【发布时间】:2020-12-31 02:34:07
【问题描述】:

用户点击后,我希望画布重新绘制,但它永远不会。我尝试使用 setState 并返回不同的画家,但似乎没有任何效果。如果我翻转屏幕或将页面替换为自身,它会被重新绘制,但这确实效率低下并且看起来不太好。我自己尝试对此进行研究,但所有潜在的答案都太令人困惑而无法理解,或者根本不起作用。任何帮助将不胜感激。

以下是代码的相关部分:

import 'package:flutter/material.dart';

class Playpage extends MaterialPageRoute<Null> {
  Playpage() : super(builder: (BuildContext ctx) {
    return Scaffold(
      appBar:PreferredSize(
        preferredSize: Size.fromHeight(40.0),
        child:AppBar(

          title: Text('Level!'),
          centerTitle: true,
        ),
      ),
      body: Container(
        color: Colors.white,
        padding: EdgeInsets.symmetric(horizontal: 50, vertical: 0),
        child: LayoutBuilder(
          // Inner yellow container
          builder: (_, constraints) => Container(
            width: constraints.widthConstraints().maxWidth,
            height: constraints.heightConstraints().maxHeight,
            color: Colors.yellow,
            child:
            GestureDetector(
              onTap: () {

                //Navigator.pushReplacement(ctx, Playpage());
              },


              onTapDown: (TapDownDetails details) => _onTapDown(details),
              child: new CustomPaint (painter: new BoardPainter()),
            ),

          ),
        ),
      ),

    );

  }
  );
}


Color colour= Colors.white;

class BoardPainter extends CustomPainter {
  @override
  bool shouldRepaint(CustomPainter oldDelegate){
    return true;}

  @override
  // TODO: draw something with canvas
  void paint(Canvas canvas, Size size){
        canvas.drawRRect(
          RRect.fromRectAndRadius(Rect.fromLTWH(200, 200, 100, 100), Radius.circular(20)),
          Paint() ..color = colour,
        );
  }
}

_onTapDown(TapDownDetails details) {
  //setState() {
colour = Colors.blue;
BoardPainter();
//}
}

【问题讨论】:

    标签: flutter dart canvas flutter-canvas


    【解决方案1】:

    documentation中所述:

    触发重绘的最有效方法是: 扩展此类并向 CustomPainter 的构造函数提供一个重绘参数,该对象在该对象通知其侦听器何时重绘。 扩展 Listenable(例如通过 ChangeNotifier)并实现 CustomPainter,以便对象本身直接提供通知。

    CustomPainter 中触发重绘的两种推荐方法之一,也是最简单的方法是通过Listenable

    我们可以这样做:

    class Playpage extends MaterialPageRoute<Null> {
     ...
    
     final _counter = ValueNotifier<int>(0);
      BoardPainter painter;
    
      @override
      void initState() {
        super.initState();
        painter = BoardPainter(repaint: _counter);
      }
    
      ...
      child: CustomPaint(
             painter: painter,
      ),
      ...
    
      ...
      bool repaint() {
        _counter.value++;
        return true;
      }
      ...
    
    }
    
    class BoardPainter extends CustomPainter {
      BoardPainter({Listenable repaint}): super(repaint: repaint);
      @override
      void paint(Canvas canvas, Size size) {
        // Draw
      }
      @override
      bool shouldRepaint(CustomPainter oldDelegate) {
        return true;
      }
    }
    

    【讨论】:

    • 你不需要_MyPainter painter; 字段 - 实际上如果你想要那个字段,不使用super(repaint: repaint) 而是使用class BoardPainter extends CustomPainter with ChangeNotifier 并在BoardPainter 中实现“重绘”方法会更容易跨度>
    • 顺便说一句:应该是_counter.value++ 而不是_counter++
    • 实际上,在我的第一条评论中,我的意思是您不需要对 CustomPainter 的任何引用(类字段),因为您不需要调用任何方法... ;-) 但是如果你的 CustomPainterChangeNotifier (class BoardPainter extends CustomPainter with ChangeNotifier) 混合在一起
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-25
    • 2020-12-13
    • 1970-01-01
    • 2019-09-08
    • 2018-11-17
    • 2020-04-22
    相关资源
    最近更新 更多