Пользовательский класс Painter не отображается в флаттере стека - PullRequest
0 голосов
/ 02 февраля 2020

По какой-то причине виджет Stack не показывает Container с CustomPaint.

Однако, если удалить из Stack, он работает нормально. Что мне здесь не хватает?

class _DemoNavBar extends State<DemoNavBar> {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return MaterialApp(
        home:
        Stack(
          children: <Widget>[
            Container(child: CustomPaint(painter: CurvePainter()))
      ],
    )
    );
  }
}

class CurvePainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    var paint = Paint();
    paint.color = Colors.green[800];
    paint.style = PaintingStyle.fill;

    var path = Path();

    path.moveTo(0, size.height - 100); 

    path.lineTo(size.width * 0.5, size.height - 100); 
    path.quadraticBezierTo(size.width * 0.7, size.height, size.width * 0.9,
        size.height - 100); 
    path.lineTo(size.width, size.height - 100); 
    path.lineTo(size.width, size.height); 
    path.lineTo(0, size.height);
    canvas.drawPath(path, paint);
  }

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

Спасибо!

1 Ответ

3 голосов
/ 02 февраля 2020

Проверка источника CustomPaint говорит:

  /// The size that this [CustomPaint] should aim for, given the layout
  /// constraints, if there is no child.
  ///
  /// Defaults to [Size.zero].
  ///
  /// If there's a child, this is ignored, and the size of the child is used
  /// instead.

Итак, дайте ему размер. Другие решения включают 1) предоставление ширины и высоты родительскому элементу Container из CustomPaint и 2) предоставление дочернего элемента для CustomPaint, который будет игнорировать size, предоставленный в приведенном ниже решении.


Я проверил этот код, чтобы он работал нормально. size: MediaQuery.of(context).size использует полный размер экрана.

void main() {
  runApp(SO());
}

class SO extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: DemoNavBar(),
    );
  }
}

class DemoNavBar extends StatefulWidget {
  @override
  _DemoNavBar createState() => _DemoNavBar();
}

class _DemoNavBar extends State<DemoNavBar> {
  @override
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget>[
        CustomPaint(
          size: MediaQuery.of(context).size,
          painter: CurvePainter(),
        )
      ],
    );
  }
}

class CurvePainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    var paint = Paint();
    paint.color = Colors.green[800];
    paint.style = PaintingStyle.fill;

    var path = Path();

    path.moveTo(0, size.height - 100);

    path.lineTo(size.width * 0.5, size.height - 100);
    path.quadraticBezierTo(size.width * 0.7, size.height, size.width * 0.9, size.height - 100);
    path.lineTo(size.width, size.height - 100);
    path.lineTo(size.width, size.height);
    path.lineTo(0, size.height);
    canvas.drawPath(path, paint);
  }

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

Теперь, причина в том, что Container не имеет родителя или потомка, чтобы обеспечить размер, он принимает полный размер экрана и прекрасно работает без Stack. Когда используется стек, размер обращается в ноль, который присваивается пользовательскому художнику.

Эквивалентный код можно записать как

Stack(
  children: <Widget>[
    Container(
      width: MediaQuery.of(context).size.width,
      height: MediaQuery.of(context).size.height,
      child: CustomPaint(
        painter: CurvePainter(),
      ),
    )
  ],
);

, конечный результат -

screenshot

...