【问题标题】:Add A Custom Decoration To Container, Using Painter Class使用 Painter 类向容器添加自定义装饰
【发布时间】:2021-02-04 12:08:47
【问题描述】:

我知道我可以给我的容器装饰,然后为它提供一个边框。 但是我正在尝试使用自定义绘制class 用一些自定义边框包裹我的Container,自定义绘制类应该围绕或提供bordercontainer,如dashed border 或任何自定义形状边框,

注意:- 请不要建议我使用任何自定义包,如虚线边框,我希望以自定义 Painter 形式的答案,如 BoxPainter 类等。

所以,到目前为止,我已经写了这个code

import 'dart:math';

import 'package:flutter/material.dart';

class CustPaint extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
          child: Container(
        width: 300,
        height: 300,
        decoration: CustomDecoration(),
        child: new Icon(Icons.wb_sunny),
      )),
    );
  }
}

class CustomDecoration extends Decoration {
  @override
  BoxPainter createBoxPainter([void Function() onChanged]) {
    return BoxDecorationPainter();
  }
}

class BoxDecorationPainter extends BoxPainter {
  @override
  void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
    final Rect bounds = offset & configuration.size;
    _drawDecoration(canvas, bounds);
  }
}

void _drawDecoration(Canvas canvas, Rect size) {
  var radius = min(size.width / 2, size.height / 2);
  var circleRaidus = radius * .012;
  var paint = Paint()
    ..color = Colors.teal
    ..strokeWidth = circleRaidus * .5
    ..style = PaintingStyle.stroke
    ..strokeCap = StrokeCap.round;

  for (int i = 0; i < 60; i++) {
    Offset topRight = Offset(size.left + i * 4, size.top);
    Offset downLeft = Offset(size.left, size.top + i * 4);
    Offset bottomRight = Offset(size.left + i * 4, size.bottom);
    Offset downRight = Offset(size.right, size.top + i * 4);

    canvas.drawCircle(topRight, circleRaidus * 2, paint);
    canvas.drawCircle(bottomRight, circleRaidus * 2, paint);
    canvas.drawCircle(downRight, circleRaidus * 2, paint);
    canvas.drawCircle(downLeft, circleRaidus * 2, paint);
  }
}

而我所取得的成就是

但是输出

  1. 我想要的是所有lines(带有小圆圈)都应该加入,并且在他们之间不应该有gap,同时会见cornercorner。 (意味着它们应该像正方形或矩形一样连接起来以覆盖容器)
  2. 另外,我想在那些微小的circles 之间给出一些space 之类的 一些padding
  3. 如果circles 可以 替换为任何image

提前致谢

【问题讨论】:

  • 您不能同时使用固定的60i * 4 - 您希望始终在每一侧都有60 圆圈,或者必须每隔4 个逻辑像素放置一个圆圈?
  • 说我想在边上有 n 个圆圈,那么我将如何在代码中实现它,它们将通过连接边形成正方形或矩形,并在这些小圆圈之间添加一些填充。跨度>
  • @pskink 实际上我尝试了你的解决方案,但我认为我以错误的方式实现了它,因为这些线不符合形成正方形或矩形,而且这些小圆圈之间也没有看到填充,也许你可以写一个答案来更清楚。
  • @pskink 您的代码运行良好,谢谢,但是您能解释一下代码吗,因为其中有很多数学,而我的数学很烂。
  • 我的意思是关于 computeMetrics 和 getTangentForOffset 和 rect.deflate

标签: flutter


【解决方案1】:

圆圈的数量必须适应盒子的大小:

final nbShapes = [
  ((bounds.width + gap) / (shapeSize + gap)).floor(),
  ((bounds.height + gap) / (shapeSize + gap)).floor(),
];

在我的解决方案中,CustomDecorationBox 可以配置为:

  • double shapeSize,形状的大小,
  • double shapeGap,两个形状之间的差距,
  • Paint shapePaint,用于绘制形状的颜料(支持笔触和填充颜料)
  • ShapePainter paintShape,绘制形状的函数

我提供了 3 个 ShapePainter 示例:

  • paintCircle()
  • paintRectangle()
  • ShapePainter createNGonPainter(int n),正边画家的工厂

完整源代码:

import 'dart:math';

import 'package:flutter/material.dart';

typedef ShapePainter = void Function(Canvas, Rect, Paint);

Random random = Random();

void main() {
  runApp(
    MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'CustomDecoration Demo',
      home: Scaffold(
        body: MyWidget(),
      ),
    ),
  );
}

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: LayoutBuilder(
        builder: (context, constraints) {
          final size = Size(1, .6) * constraints.biggest.width;
          print(size);
          return GridView.count(
            crossAxisCount: 3,
            children: List.generate(
              120,
              (index) => Padding(
                padding: EdgeInsets.all(size.width * .01),
                child: Container(
                  decoration: CustomDecoration(
                    shapeSize: 5.0 + random.nextInt(10),
                    shapeGap: 2.0 + random.nextInt(3),
                    shapePaint: Paint()
                      ..color = Color(0x99000000 + random.nextInt(0xffffff))
                      ..strokeWidth = random.nextInt(3).toDouble()
                      ..style = random.nextInt(3) == 2
                          ? PaintingStyle.fill
                          : PaintingStyle.stroke,
                    paintShape: random.nextInt(4) == 0
                        ? paintCircle
                        : createNGonPainter(3 + random.nextInt(5)),
                  ),
                  child: Center(
                    child: Text(
                      index.toString(),
                      style: TextStyle(fontSize: 24.0),
                    ),
                  ),
                ),
              ),
            ),
          );
        },
      ),
    );
  }
}

class CustomDecoration extends Decoration {
  final double shapeSize;
  final double shapeGap;
  final Paint shapePaint;
  final ShapePainter paintShape;

  CustomDecoration({
    this.shapeSize,
    this.shapeGap,
    this.shapePaint,
    this.paintShape,
  }) : super();

  @override
  BoxPainter createBoxPainter([void Function() onChanged]) {
    return BoxDecorationPainter(
        shapeSize: shapeSize ?? 10,
        shapeGap: shapeGap ?? 4,
        shapePaint: shapePaint ?? Paint(),
        paintShape: paintShape ?? paintCircle);
  }
}

class BoxDecorationPainter extends BoxPainter {
  final double shapeSize;
  final double shapeGap;
  final Paint shapePaint;
  final ShapePainter paintShape;

  BoxDecorationPainter({
    this.shapeSize,
    this.shapeGap,
    this.shapePaint,
    this.paintShape,
  }) : super();

  @override
  void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
    final Rect bounds = offset & configuration.size;
    _drawDecoration(canvas, bounds, shapeSize, shapeGap);
  }

  void _drawDecoration(
      Canvas canvas, Rect bounds, double shapeSize, double gap) {
    final nbShapes = [
      ((bounds.width + gap) / (shapeSize + gap)).floor(),
      ((bounds.height + gap) / (shapeSize + gap)).floor(),
    ];
    final correctedGaps = [
      (bounds.width - nbShapes[0] * shapeSize) / (nbShapes[0] - 1),
      (bounds.height - nbShapes[1] * shapeSize) / (nbShapes[1] - 1),
    ];
    final steps = [
      correctedGaps[0] + shapeSize,
      correctedGaps[1] + shapeSize,
    ];

    for (int i = 0; i < nbShapes[0]; i++) {
      paintShape(
        canvas,
        Rect.fromLTWH(
          bounds.left + steps[0] * i,
          bounds.top,
          shapeSize,
          shapeSize,
        ),
        shapePaint,
      );
      paintShape(
        canvas,
        Rect.fromLTWH(
          bounds.left + steps[0] * i,
          bounds.bottom - shapeSize,
          shapeSize,
          shapeSize,
        ),
        shapePaint,
      );
    }

    for (int i = 1; i < nbShapes[1] - 1; i++) {
      paintShape(
        canvas,
        Rect.fromLTWH(
          bounds.left,
          bounds.top + steps[1] * i,
          shapeSize,
          shapeSize,
        ),
        shapePaint,
      );
      paintShape(
        canvas,
        Rect.fromLTWH(
          bounds.right - shapeSize,
          bounds.top + steps[1] * i,
          shapeSize,
          shapeSize,
        ),
        shapePaint,
      );
    }
  }
}

void paintCircle(Canvas canvas, Rect bounds, Paint paint) {
  canvas.drawCircle(
    Offset(
      bounds.left + bounds.width / 2,
      bounds.top + bounds.height / 2,
    ),
    bounds.shortestSide / 2,
    paint,
  );
}

void paintRectangle(Canvas canvas, Rect bounds, Paint paint) {
  canvas.drawRect(bounds, paint);
}

ShapePainter createNGonPainter(int n) => (canvas, bounds, paint) {
      Path path = Path();
      path.moveTo(
        bounds.left + (bounds.width + cos(2 * pi / n) * bounds.width) / 2,
        bounds.top + (bounds.height + sin(2 * pi / n) * bounds.height) / 2,
      );
      for (var k = 2; k <= n; k++) {
        path.lineTo(
          bounds.left + (bounds.width + cos(2 * k * pi / n) * bounds.width) / 2,
          bounds.top +
              (bounds.height + sin(2 * k * pi / n) * bounds.height) / 2,
        );
      }
      path.close();
      canvas.drawPath(path, paint);
    };

【讨论】:

  • 您的代码可以按照我的要求完美运行,但是您忘记在这些圆圈之间添加填充,请您添加这些。
  • 天空是极限!我会用更多的数学来更新我的答案,尤其是对你来说。 ?
猜你喜欢
  • 1970-01-01
  • 2021-12-25
  • 1970-01-01
  • 2018-01-12
  • 1970-01-01
  • 1970-01-01
  • 2013-02-06
  • 1970-01-01
  • 2021-11-25
相关资源
最近更新 更多