07-21-2023, 09:03 PM
I'm trying to extend the `ShapeBorder` class to add some functionality. But just playing around with the `paint` method, I found something that I did not expect:
[![enter image description here][1]][1]
The corners of the border and the corners of the rectangle do not seem to match. I used the following code:
class CustomRoundedRectangleBorder extends ShapeBorder {
final double borderWidth;
final BorderRadius borderRadius;
const CustomRoundedRectangleBorder({
this.borderWidth: 1.0,
this.borderRadius: BorderRadius.zero,
})
: assert(borderRadius != null);
@override
EdgeInsetsGeometry get dimensions {
return new EdgeInsets.all(borderWidth);
}
@override
ShapeBorder scale(double t) {
return new CustomRoundedRectangleBorder(
borderWidth: borderWidth * (t),
borderRadius: borderRadius * (t),
);
}
@override
ShapeBorder lerpFrom(ShapeBorder a, double t) {
assert(t != null);
if (a is CustomRoundedRectangleBorder) {
return new CustomRoundedRectangleBorder(
borderWidth: ui.lerpDouble(a.borderWidth, borderWidth, t),
borderRadius: BorderRadius.lerp(a.borderRadius, borderRadius, t),
);
}
return super.lerpFrom(a, t);
}
@override
ShapeBorder lerpTo(ShapeBorder b, double t) {
assert(t != null);
if (b is CustomRoundedRectangleBorder) {
return new CustomRoundedRectangleBorder(
borderWidth: ui.lerpDouble(borderWidth, b.borderWidth, t),
borderRadius: BorderRadius.lerp(borderRadius, b.borderRadius, t),
);
}
return super.lerpTo(b, t);
}
@override
Path getInnerPath(Rect rect, { TextDirection textDirection }) {
return new Path()
..addRRect(borderRadius.resolve(textDirection).toRRect(rect).deflate(
borderWidth));
}
@override
Path getOuterPath(Rect rect, { TextDirection textDirection }) {
return new Path()
..addRRect(borderRadius.resolve(textDirection).toRRect(rect));
}
@override
void paint(Canvas canvas, Rect rect, { TextDirection textDirection }) {
rect = rect.deflate(borderWidth / 2.0);
Paint paint;
final RRect borderRect = borderRadius.resolve(textDirection).toRRect(rect);
paint = new Paint()
..color = Colors.red
..style = PaintingStyle.stroke
..strokeWidth = borderWidth;
canvas.drawRRect(borderRect, paint);
}
}
And created the rectangle as follows:
new Container(
height: 100.0,
width: 200.0,
padding: new EdgeInsets.all(10.0),
decoration: new ShapeDecoration(
color: Colors.black,
shape: new CustomRoundedRectangleBorder(
borderRadius: new BorderRadius.all(new Radius.circular(20.0)),
borderWidth: 10.0,
),
// side: new BorderSide(color: Colors.white)
),
child: new Center(child: new Text("My Button"),),
),
I feel like the Flutter source code takes a similar approach, but perhaps I'm not seeing something.
**EDIT**
Changing the `style` of my `paint` to `PaintingStyle.fill` thus drawing a rectangle over the original rectangle instead of borders, I do seem to get the correct borders:
void paint(Canvas canvas, Rect rect, { TextDirection textDirection }) {
// rect = rect.deflate(borderWidth / 2.0);
Paint paint;
final RRect borderRect = borderRadius.resolve(textDirection).toRRect(rect);
paint = new Paint()
..color = Colors.red.withOpacity(0.25)
..style = PaintingStyle.fill
..strokeWidth = borderWidth;
canvas.drawRRect(borderRect, paint);
}
I'm still puzzled on how to do this...
[1]:
[![enter image description here][1]][1]
The corners of the border and the corners of the rectangle do not seem to match. I used the following code:
class CustomRoundedRectangleBorder extends ShapeBorder {
final double borderWidth;
final BorderRadius borderRadius;
const CustomRoundedRectangleBorder({
this.borderWidth: 1.0,
this.borderRadius: BorderRadius.zero,
})
: assert(borderRadius != null);
@override
EdgeInsetsGeometry get dimensions {
return new EdgeInsets.all(borderWidth);
}
@override
ShapeBorder scale(double t) {
return new CustomRoundedRectangleBorder(
borderWidth: borderWidth * (t),
borderRadius: borderRadius * (t),
);
}
@override
ShapeBorder lerpFrom(ShapeBorder a, double t) {
assert(t != null);
if (a is CustomRoundedRectangleBorder) {
return new CustomRoundedRectangleBorder(
borderWidth: ui.lerpDouble(a.borderWidth, borderWidth, t),
borderRadius: BorderRadius.lerp(a.borderRadius, borderRadius, t),
);
}
return super.lerpFrom(a, t);
}
@override
ShapeBorder lerpTo(ShapeBorder b, double t) {
assert(t != null);
if (b is CustomRoundedRectangleBorder) {
return new CustomRoundedRectangleBorder(
borderWidth: ui.lerpDouble(borderWidth, b.borderWidth, t),
borderRadius: BorderRadius.lerp(borderRadius, b.borderRadius, t),
);
}
return super.lerpTo(b, t);
}
@override
Path getInnerPath(Rect rect, { TextDirection textDirection }) {
return new Path()
..addRRect(borderRadius.resolve(textDirection).toRRect(rect).deflate(
borderWidth));
}
@override
Path getOuterPath(Rect rect, { TextDirection textDirection }) {
return new Path()
..addRRect(borderRadius.resolve(textDirection).toRRect(rect));
}
@override
void paint(Canvas canvas, Rect rect, { TextDirection textDirection }) {
rect = rect.deflate(borderWidth / 2.0);
Paint paint;
final RRect borderRect = borderRadius.resolve(textDirection).toRRect(rect);
paint = new Paint()
..color = Colors.red
..style = PaintingStyle.stroke
..strokeWidth = borderWidth;
canvas.drawRRect(borderRect, paint);
}
}
And created the rectangle as follows:
new Container(
height: 100.0,
width: 200.0,
padding: new EdgeInsets.all(10.0),
decoration: new ShapeDecoration(
color: Colors.black,
shape: new CustomRoundedRectangleBorder(
borderRadius: new BorderRadius.all(new Radius.circular(20.0)),
borderWidth: 10.0,
),
// side: new BorderSide(color: Colors.white)
),
child: new Center(child: new Text("My Button"),),
),
I feel like the Flutter source code takes a similar approach, but perhaps I'm not seeing something.
**EDIT**
Changing the `style` of my `paint` to `PaintingStyle.fill` thus drawing a rectangle over the original rectangle instead of borders, I do seem to get the correct borders:
void paint(Canvas canvas, Rect rect, { TextDirection textDirection }) {
// rect = rect.deflate(borderWidth / 2.0);
Paint paint;
final RRect borderRect = borderRadius.resolve(textDirection).toRRect(rect);
paint = new Paint()
..color = Colors.red.withOpacity(0.25)
..style = PaintingStyle.fill
..strokeWidth = borderWidth;
canvas.drawRRect(borderRect, paint);
}
I'm still puzzled on how to do this...
[1]: