How can I create a custom widget like this in Flutter?

This is the required widget

image

I have tried using Stack. But didn’t got correct solution

>Solution :

You can achieve this first you need to calculate the Text widget to draw that blue underline with that same width of the text using TextPainter and LayoutBuilder:

class TextPainterWidget extends StatelessWidget {
  final TextPainter textPainter;

  const TextPainterWidget({
    Key? key,
    required this.textPainter,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return CustomPaint(
      painter: _TextPainterWidget(textPainter),
    );
  }
}

class _TextPainterWidget extends CustomPainter {
  final TextPainter textPainter;

  _TextPainterWidget(this.textPainter);

  @override
  void paint(Canvas canvas, Size size) {
    textPainter.layout();
    textPainter.paint(canvas, Offset.zero);
  }

  @override
  bool shouldRepaint(_TextPainterWidget oldDelegate) {
    return oldDelegate.textPainter.text != textPainter.text ||
        oldDelegate.textPainter.text?.style != textPainter.text?.style;
  }
}

Then Your main widget should be like that:

            LayoutBuilder(
              builder: (BuildContext context, BoxConstraints constraints) {
                final TextPainter textPainter = TextPainter(
                  text: const TextSpan(
                    text: 'Grab The Best Deal On ',
                    style: TextStyle(
                      color: Colors.black,
                      fontWeight: FontWeight.bold,
                    ),
                    children: <TextSpan>[
                      TextSpan(
                        text: 'Smartphones',
                        style: TextStyle(
                          color: Colors.blue,
                          fontWeight: FontWeight.bold,
                        ),
                      ),
                    ],
                  ),
                  textDirection: TextDirection.ltr,
                )..layout(maxWidth: constraints.maxWidth);

                final double textWidth = textPainter.width;

                return Column(
                  children: <Widget>[
                    Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: <Widget>[
                        TextPainterWidget(textPainter: textPainter),
                        Row(
                          children: <Widget>[
                            const Text('View All'),
                            const SizedBox(width: 8),
                            InkWell(
                              onTap: () {},
                              child: const Icon(
                                Icons.arrow_forward_ios,
                                size: 15,
                                color: Colors.blue,
                              ),
                            ),
                          ],
                        ),
                      ],
                    ),
                    Row(
                      children: <Widget>[
                        SizedBox(
                          width: textWidth,
                          child: const Divider(
                            color: Colors.blue,
                            thickness: 2,
                          ),
                        ),
                        const Expanded(
                          child: Divider(
                            color: Colors.grey,
                            thickness: 1,
                          ),
                        ),
                      ],
                    ),
                  ],
                );
              },
            ),

Leave a Reply