I have been trying to create something like this in Flutter,
I tried using CustomPaint for it because of the bottom right sharp thing. and I use stack to set texts on it.
The problem is that this is not responsive; on some devices, texts are not where they should be. how can I fix this?
The widget
Stack(
alignment: widget.alignment,
children: [
CustomPaint(
size: Size(context.width, ((context.width) * 0.58).toDouble()),
painter: widget.painterWidget ,
),
Padding(
padding: EdgeInsets.only(
right: 8.0,
left: 8.0,
),
child: SizedBox(
width: context.width,
child: Column(
....
The CustomPaint
class NotificationCustomPainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
// Layer 1
Paint paint_fill_0 = Paint()
..color = const Color.fromARGB(255, 255, 255, 255)
..style = PaintingStyle.fill
..strokeWidth = size.width * 0.00
..strokeCap = StrokeCap.butt
..strokeJoin = StrokeJoin.miter;
Path path_0 = Path();
path_0.moveTo(size.width * 0.9608333, size.height * 0.0714286);
path_0.quadraticBezierTo(
size.width * 0.9980167, size.height * 0.0702571, size.width * 1.0025000, size.height * 0.1414286);
path_0.cubicTo(size.width * 1.0020833, size.height * 0.2489286, size.width * 1.0017917,
size.height * 0.5629000, size.width * 1.0013750, size.height * 0.6704000);
path_0.quadraticBezierTo(
size.width * 1.0005583, size.height * 0.7403286, size.width * 0.9597083, size.height * 0.7454000);
path_0.quadraticBezierTo(
size.width * 0.2732333, size.height * 0.7409286, size.width * 0.0432333, size.height * 0.7409286);
path_0.quadraticBezierTo(
size.width * 0.0030750, size.height * 0.7389714, size.width * -0.0011833, size.height * 0.6743571);
path_0.quadraticBezierTo(
size.width * 0.0008833, size.height * 0.2457071, size.width * 0.0009000, size.height * 0.1366571);
path_0.quadraticBezierTo(
size.width * -0.0007333, size.height * 0.0698000, size.width * 0.0441667, size.height * 0.0700000);
path_0.lineTo(size.width * 0.0516167, size.height * 0.0029429);
path_0.lineTo(size.width * 0.0800000, size.height * 0.0677000);
canvas.drawPath(path_0, paint_fill_0);
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return true;
}
}
You can use ShapeBorder
for this. Play on gist or dartPad
/// Create a pointy shape like toolTip
///
/// ```dart
/// Container(
/// decoration: ShapeDecoration(
/// shape: PointyShape(
/// padding: const EdgeInsets.all(12),
/// pointOffsetX: pointX,
/// pointyHeight: 24,
/// radiusValue: 16,
/// isTop : true,
/// ),
/// color: Colors.white,
/// ),
///```
///
class PointyShape extends OutlinedBorder {
const PointyShape({
this.pointOffsetX = .85,
this.radiusValue = 16,
this.pointyHeight = 24,
this.padding = const EdgeInsets.all(12),
this.isTop = true,
}) : assert(pointOffsetX >= 0 && pointOffsetX <= 1, "offset should be within 0,1");
final double pointOffsetX;
final double radiusValue;
final double pointyHeight;
final EdgeInsets padding;
final bool isTop;
@override
OutlinedBorder copyWith({BorderSide? side}) => this;
@override
EdgeInsetsGeometry get dimensions => padding.copyWith(
bottom: padding.bottom + (isTop ? 0 : pointyHeight),
top: padding.top + (isTop ? pointyHeight : 0),
);
@override
Path getInnerPath(Rect rect, {TextDirection? textDirection}) {
return getOuterPath(rect, textDirection: textDirection);
}
@override
Path getOuterPath(Rect rect, {TextDirection? textDirection}) {
final rRect = RRect.fromRectAndRadius(
Rect.fromLTRB(
rect.left,
rect.top + (isTop ? pointyHeight : 0),
rect.right,
rect.bottom - (isTop ? 0 : pointyHeight),
),
Radius.circular(radiusValue),
);
final pointyStartX = rect.right - (rect.width * (1 - pointOffsetX)) - pointyHeight / 2;
final toolTip = isTop
? (Path()
..moveTo(pointyStartX + pointyHeight / 2, rect.top)
..lineTo(pointyStartX, rect.top + pointyHeight)
..lineTo(pointyStartX + (pointyHeight), rect.top + pointyHeight)
..lineTo(pointyStartX + pointyHeight / 2, rect.top))
: Path()
..moveTo(
pointyStartX,
rect.bottom - pointyHeight,
)
..lineTo(pointyStartX + (pointyHeight / 2), rect.bottom)
..lineTo(pointyStartX + (pointyHeight), rect.bottom - pointyHeight)
..lineTo(pointyStartX, rect.bottom - pointyHeight);
return Path.combine(PathOperation.union, Path()..addRRect(rRect), toolTip);
}
@override
void paint(Canvas canvas, Rect rect, {TextDirection? textDirection}) {}
@override
ShapeBorder scale(double t) => this;
}