5

Hi how do i create box container with arrow on top without using any pub packages.

Like below.

enter image description here

5
  • stackoverflow.com/a/57943257/2252830
    – pskink
    Commented Jul 17, 2020 at 10:39
  • You can use Stack widget containing the container and the arrow icon Commented Jul 17, 2020 at 10:44
  • 1
    hi @pskink how can i make it top center ?
    – Jai Techie
    Commented Jul 19, 2020 at 5:34
  • did you see ..moveTo(rect.bottomCenter.dx - 10, rect.bottomCenter.dy) in my code?
    – pskink
    Commented Jul 19, 2020 at 5:36
  • 2
    @pskink yes i changed to ..moveTo(rect.topCenter.dx - 20, rect.topCenter.dy) ..relativeLineTo(20, -20) ..relativeLineTo(10, 20) this and now arrow is in topcenter working. thanks
    – Jai Techie
    Commented Jul 19, 2020 at 5:43

3 Answers 3

1

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();
1
  • We also need to update the y of relativeLineTo to make up arrow. @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(); }
    – NhatVM
    Commented Oct 11, 2022 at 3:09
0

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)
0

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

enter image description here

Not the answer you're looking for? Browse other questions tagged or ask your own question.