如何在 Flutter 中使用两个自定义画家?

问题描述 投票:0回答:3

我做了2个定制画家

1.

class DrawTriangle1 extends CustomPainter {
  DrawTriangle1() {
    painter = Paint()
      ..shader =
          LinearGradient(colors: [Colors.red, Colors.white]).createShader(rect)
      ..style = PaintingStyle.fill;
  }

  @override
  void paint(Canvas canvas, Size size) {
    var path = Path();

    path.moveTo(0, 0);
    path.lineTo(size.width, 0);
    path.lineTo(size.width, size.height / 2);
    path.close();
    canvas.drawPath(path, painter);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return true;
  }
}
class DrawTriangle2 extends CustomPainter {
  DrawTriangle2() {
    painter = Paint()
      ..shader = LinearGradient(colors: [
        Color(0xfffff),
        Color(0xff076585),
      ]).createShader(rect)
      ..style = PaintingStyle.fill;
  }

  @override
  void paint(Canvas canvas, Size size) {
    var path = Path();
    path.lineTo(size.width / 2, size.height / 4);
    path.lineTo(0, size.height / 2);
    path.close();

    canvas.drawPath(path, painter);
  }

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

如果我使用自定义画家来制作单个形状。画家从页面的开头开始绘制。

ListView(
          children: <Widget>[
            CustomPaint(
              painter: DrawTriangle1(),
              size: Size(MediaQuery.of(context).size.width,
          MediaQuery.of(context).size.height), ,
            )
          ],
        )

但是如果我像这样向列表视图添加另一个。第二个三角形从第一个屏幕的底部开始。

ListView(
          children: <Widget>[
            CustomPaint(
              painter: DrawTriangle1(),
              size: Size(MediaQuery.of(context).size.width,
                  MediaQuery.of(context).size.height),
            ),
            CustomPaint(
              painter: DrawTriangle2(),
              size: Size(MediaQuery.of(context).size.width,
                  MediaQuery.of(context).size.height),
            )
          ],
        ),

如何使两者具有相同的起点?

flutter flutter-canvas
3个回答
1
投票

ListView 逐个构建它的每个子级,因此如果您想在堆栈小部件方便的同一位置做一些工作,这是预期的行为。它将允许您在同一位置绘制两个自定义画家。

因此,将 ListView 小部件替换为 stack Widget 将解决您的问题。

Stack( //change 
          children: <Widget>[
            CustomPaint(
              painter: DrawTriangle1(),
              size: Size(MediaQuery.of(context).size.width,
                  MediaQuery.of(context).size.height),
            ),
            CustomPaint(
              painter: DrawTriangle2(),
              size: Size(MediaQuery.of(context).size.width,
                  MediaQuery.of(context).size.height),
            )
          ],
        ),

1
投票

使用堆栈。

@override
  Widget build(BuildContext context) {
    return Stack(children: [
            CustomPaint(
              painter: DrawTriangle1(),
              size: Size(MediaQuery.of(context).size.width,
                  MediaQuery.of(context).size.height),
            ),
            CustomPaint(
              painter: DrawTriangle2(),
              size: Size(MediaQuery.of(context).size.width,
                  MediaQuery.of(context).size.height),
            )
          ]);
  }

0
投票

要组合两个 CustomPainter,您需要创建一个新类,将它们作为输入,然后在其重写的 Paint(Canvas, Size) 函数中绘制它们。

我没有设法解决的唯一问题是 shouldRepaint() 函数,所以我总是在那里返回 true,因为在我的情况下,它需要在每一帧中重新绘制。

这是我的实现:

import 'package:flutter/material.dart';

class CombinedPainter extends CustomPainter {
  const CombinedPainter(this.customPainters, this.customPainter2);

  final CustomPainter customPainter1;
  final CustomPainter customPainter2;

  @override
  void paint(Canvas canvas, Size size) {
    customPainter1.paint(canvas, size);

    customPainter2.paint(canvas, size);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    // Change this depending on your needs
    return true;
  }
}

您还可以使其能够处理无数的 CustomPainter:

import 'package:flutter/material.dart';

class CombinedPainter extends CustomPainter {
  const CombinedPainter(this.customPainters);

  final List<CustomPainter> customPainters;

  @override
  void paint(Canvas canvas, Size size) {
    for (customPainter in customPainters) {
      customPainter.paint(canvas, size);
    }
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    // Change this depending on your needs
    return true;
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.