Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
354 views
in Technique[技术] by (71.8m points)

flutter - Add A Custom Decoration To Container, Using Painter Class

I know I can give decoration to my container, and then provide a border to it. But I am trying to Wrap my Container with some Custom border using Custom Paint class, The Custom Paint Class should surround or provide a border to container like a dashed border or any custom shape border,

Note:- Please Don't suggest me to use any custom package like dashed Border, I want the answer in the form of Custom Painter like BoxPainter class etc.

So, Far I have wrote this 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);
  }
}

And What I have Achieved is

enter image description here

But The OUTPUT

  1. I want is that all the lines (with tiny circles) should join and there should be no gap in between them while meeting corner to corner. (means they should join to cover the container like a square or rectangle)
  2. Also I want to give some space between those tiny circles like some padding.
  3. It would be a plus if those circles can be replaced by any image.

Thanks in Advance

question from:https://stackoverflow.com/questions/66045318/add-a-custom-decoration-to-container-using-painter-class

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

The number of circles has to be adapted to the size of the box:

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

enter image description here

In my Solution, the CustomDecorationBox can be configured with:

  • double shapeSize, the size of the shapes,
  • double shapeGap, the gap between two shapes,
  • Paint shapePaint, the paint used to draw the shapes (support for both strokes and fill paints)
  • ShapePainter paintShape, a function painting the shapes

I provided 3 ShapePainter samples:

  • paintCircle()
  • paintRectangle()
  • ShapePainter createNGonPainter(int n), a factory for n-gon painters

Full source code:

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...