Search code examples
flutterflutter-text

Flutter: how to make TextOverflow.ellipse in the middle of Text


enter image description here

I need to create a UI like the image above, but it is not related to the length of the string. It will be limited to the width of the parent Widget that contains it.

I did some reseach and see the same problem here but there is no answer can resolve my problem

I also found the package extendex_text but it's too heavy to add just for a small problem like this.


Solution

  • Use the below custom widget to achieve the text ellipse in the middle of the string.

    class MiddleEllipsisText extends StatelessWidget {
      final String text;
      final TextStyle? style;
    
      const MiddleEllipsisText({super.key, required this.text, this.style});
    
      @override
      Widget build(BuildContext context) {
        return LayoutBuilder(
          builder: (BuildContext context, BoxConstraints constraints) {
            // Measure the width of the text
            final textPainter = TextPainter(
              text: TextSpan(text: text, style: style),
              maxLines: 1,
              textDirection: TextDirection.ltr,
            )..layout(minWidth: 0, maxWidth: double.infinity);
    
            if (textPainter.width <= constraints.maxWidth) {
              // Text fits without truncation
              return Text(text, style: style);
            }
    
            // Calculate the truncation point
            final ellipsis = '...';
            final ellipsisPainter = TextPainter(
              text: TextSpan(text: ellipsis, style: style),
              maxLines: 1,
              textDirection: TextDirection.ltr,
            )..layout(minWidth: 0, maxWidth: double.infinity);
    
            final ellipsisWidth = ellipsisPainter.width;
            final availableWidth = constraints.maxWidth - ellipsisWidth;
            final charWidth = textPainter.width / text.length;
    
            // Determine the number of characters that can fit on each side of the ellipsis
            final charsToShow = (availableWidth / (2 * charWidth)).floor();
            final startText = text.substring(0, charsToShow);
            final endText = text.substring(text.length - charsToShow);
    
            // Create the final truncated text
            final truncatedText = '$startText$ellipsis$endText';
    
            return Text(truncatedText, style: style);
          },
        );
      }
    }
    

    And use it like below,

    Widget build(BuildContext context) {
        return const Scaffold(
            body: Center(
                child: SizedBox(
          width: 200,
          child: MiddleEllipsisText(
            text: '0b8931141868658618615312e2a80Ea5f',
            style: TextStyle(fontSize: 18),
          ),
        )));
      }
    

    Below is the output

    enter image description here