Hi how do i create box container with arrow on top without using any pub packages.
Like below.
You can customize ShapeBorder similar to this post. Then instead of using rect.bottomCenter
for Path(), change it to rect.TopCenter
to place the drawn Rect at the top.
Path()dart
..addRRect(RRect.fromRectAndRadius(rect, Radius.circular(rect.height / 2)))
..moveTo(rect.topCenter.dx - 10, rect.topCenter.dy)
..relativeLineTo(10, 20)
..relativeLineTo(20, -20)
..close();
For my case, I customized a shapeborder for flutter tooltip.
class TooltipShippingFeeBorder extends ShapeBorder{
@override
EdgeInsetsGeometry get dimensions => const EdgeInsets.only(top:20);
@override
Path getInnerPath(Rect rect, {TextDirection? textDirection}) {
return Path()
..fillType = PathFillType.evenOdd
..addPath(getOuterPath(rect), Offset.zero);
}
@override
Path getOuterPath(Rect rect, {TextDirection? textDirection}) {
rect = Rect.fromPoints(rect.topLeft, rect.bottomRight - Offset(0, 20));
return Path()
..addRRect(RRect.fromRectAndRadius(rect, const Radius.circular(6)))
..moveTo(rect.topCenter.dx - 10, rect.topCenter.dy)
..relativeLineTo(10, -20)
..relativeLineTo(20, 20)
..close();
}
@override
void paint(Canvas canvas, Rect rect, {TextDirection? textDirection}) {
}
@override
ShapeBorder scale(double t) => this;
}
And use it on tooltip like this:
Tooltip(
triggerMode: TooltipTriggerMode.tap,
padding: const EdgeInsets.only(bottom: 16, left: 10, right: 10),
decoration: ShapeDecoration(
shape: TooltipShippingFeeBorder(),
color: WalletTheme.primaryColor),
message: '$shippingFeeMessage\n',
child: const Icon(
Icons.info_outline,
size: 16,
color: WalletTheme.grey2,
),
)
So in your case, you also create the same border and use ShapreDecoration for Container.
ShapeDecoration(
shape: TooltipShippingFeeBorder(),
color: WalletTheme.primaryColor)
add this widget with managing isShow status,
Stack(
alignment: Alignment.centerRight,
children: [
Align(
alignment: Alignment.centerLeft,
child: Visibility(
visible: isShow,
child: const TestScreens(),
),
),
const Center(
child: Text(
'Domestic Fixed Deposits plus',
style: TextStyle(
fontSize: 20,
color: Colors.black,
letterSpacing: 3,
fontWeight: FontWeight.bold),
),
),
],
),
Custom box container with a triangle arrow on top
import 'package:flutter/material.dart';
class TestScreens extends StatefulWidget {
const TestScreens({super.key});
@override
State<TestScreens> createState() => _TestScreensState();
}
class _TestScreensState extends State<TestScreens>
with SingleTickerProviderStateMixin {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
Center(
child: CustomPaint(
painter: TrianglePainter(
strokeColor: Colors.blue,
strokeWidth: 0,
paintingStyle: PaintingStyle.fill,
),
child: const SizedBox(
height: 15,
width: 25,
),
),
),
Container(
color: Colors.blue,
width: 150.0,
height: 100.0,
child: const Center(
child: Text('Rectangle'),
),
),
],
),
);
}
}
class TrianglePainter extends CustomPainter {
final Color strokeColor;
final PaintingStyle paintingStyle;
final double strokeWidth;
TrianglePainter(
{this.strokeColor = Colors.black,
this.strokeWidth = 3,
this.paintingStyle = PaintingStyle.stroke});
@override
void paint(Canvas canvas, Size size) {
Paint paint = Paint()
..color = strokeColor
..strokeWidth = strokeWidth
..style = paintingStyle;
canvas.drawPath(getTrianglePath(size.width, size.height), paint);
}
Path getTrianglePath(double x, double y) {
return Path()
..moveTo(0, y)
..lineTo(x / 2, 0)
..lineTo(x, y)
..lineTo(0, y);
}
@override
bool shouldRepaint(TrianglePainter oldDelegate) {
return oldDelegate.strokeColor != strokeColor ||
oldDelegate.paintingStyle != paintingStyle ||
oldDelegate.strokeWidth != strokeWidth;
}
}
..moveTo(rect.bottomCenter.dx - 10, rect.bottomCenter.dy)
in my code?