Skip to content

Instantly share code, notes, and snippets.

@mrasityilmaz
Last active January 19, 2025 13:59
Show Gist options
  • Save mrasityilmaz/becfe73cc59f06a76d565a66fa537c04 to your computer and use it in GitHub Desktop.
Save mrasityilmaz/becfe73cc59f06a76d565a66fa537c04 to your computer and use it in GitHub Desktop.
MultipleBorderBoxDecoration
import 'package:flutter/material.dart';
class MultiBorderBoxDecoration extends BoxDecoration {
MultiBorderBoxDecoration({
required this.borderSides,
this.boxShape = BoxShape.rectangle,
super.color,
super.image,
BorderRadius? super.borderRadius,
super.boxShadow,
super.gradient,
super.backgroundBlendMode,
}) : assert(borderSides.isNotEmpty, 'borderSides cannot be empty'),
assert(
boxShape == BoxShape.rectangle || borderRadius == null,
'[boxShape] cannot be circle when [borderRadius] is used.',
),
super(
shape: boxShape,
);
final List<BorderSide> borderSides;
final BoxShape boxShape;
@override
BoxPainter createBoxPainter([VoidCallback? onChanged]) {
return _MultiBorderBoxPainter(this, onChanged);
}
}
class _MultiBorderBoxPainter extends BoxPainter {
_MultiBorderBoxPainter(this._decoration, VoidCallback? onChanged) : super(onChanged);
final MultiBorderBoxDecoration _decoration;
@override
void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
final Rect rect = offset & configuration.size!;
final Paint paint = Paint();
_paintBackground(canvas, rect, configuration.textDirection);
double currentRadius = 0;
for (final borderSide in _decoration.borderSides) {
paint
..color = borderSide.color
..style = PaintingStyle.stroke
..strokeWidth = borderSide.width
..filterQuality = FilterQuality.high
..strokeJoin = StrokeJoin.round
..strokeCap = StrokeCap.round;
if (_decoration.boxShape == BoxShape.rectangle) {
final RRect rrect = RRect.fromRectAndCorners(
rect.deflate(currentRadius),
topLeft: _decoration.borderRadius!.resolve(TextDirection.ltr).topLeft - Radius.circular(currentRadius),
topRight: _decoration.borderRadius!.resolve(TextDirection.ltr).topRight - Radius.circular(currentRadius),
bottomLeft: _decoration.borderRadius!.resolve(TextDirection.ltr).bottomLeft - Radius.circular(currentRadius),
bottomRight:
_decoration.borderRadius!.resolve(TextDirection.ltr).bottomRight - Radius.circular(currentRadius),
);
canvas.drawRRect(rrect, paint);
} else if (_decoration.boxShape == BoxShape.circle) {
final double radius = (rect.shortestSide / 2.0) - currentRadius;
canvas.drawCircle(rect.center, radius, paint);
}
currentRadius += borderSide.width;
}
}
void _paintBackground(Canvas canvas, Rect rect, TextDirection? textDirection) {
if (_decoration.color != null || _decoration.gradient != null) {
final Paint paint = Paint();
if (_decoration.gradient != null) {
paint.shader = _decoration.gradient!.createShader(rect, textDirection: textDirection);
} else if (_decoration.color != null) {
paint.color = _decoration.color!;
}
if (_decoration.boxShape == BoxShape.circle) {
final double radius = rect.shortestSide / 2.0;
canvas.drawCircle(rect.center, radius, paint);
} else {
canvas.drawRRect(
_decoration.borderRadius?.resolve(textDirection).toRRect(rect) ?? RRect.fromRectAndCorners(rect),
paint,
);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment