fluttertextflutter-layouttruncated

Flutter: Alternative text when truncated


In some Text Widgets we display text which is getting truncated on some devices and we want to replace the text in this cases instead of truncating it.

I.E. we display a name like "Kamala Devi Harris"

When the name is too long for displaying we want to call a method and transform it to "Kamala D. Harris" and if that is also to long then "K. D. Harris" ... "K. Harris" or even "K. H."

How can we recognize that the current text is getting truncated?


Solution

  • I don't know if it's the most suitable way to achieve what you're trying to do but here's how we can do it :

    Make a custom Widget which will take a list of String from greater value to lower so that it can check which value fit's in the available space.

    class OverflowAwareText extends StatefulWidget {
      final List<String> alternativeTexts;
      OverflowAwareText({this.alternativeTexts});
      @override
      _OverflowAwareText createState() => _OverflowAwareText();
    }
    
    class _OverflowAwareText extends State<OverflowAwareText> {
      List<String> texts;
      int activeTextIndex = 0;
    
      @override
      void initState() {
        super.initState();
        texts = widget.alternativeTexts;
      }
    
      @override
      Widget build(BuildContext context) {
        return LayoutBuilder(builder: (context, size) {
          var textSpan = TextSpan(
            text: texts[activeTextIndex],
            style: TextStyle(fontSize: 42),
          );
          // Use a textpainter to determine if it will exceed max lines
          var textPainter = TextPainter(
            maxLines: 1,
            textAlign: TextAlign.left,
            textDirection: TextDirection.ltr,
            text: textSpan,
          )..layout(maxWidth: size.maxWidth);
    
          if (textPainter.didExceedMaxLines) {
            if (activeTextIndex != texts.length - 1) {
              WidgetsBinding.instance.addPostFrameCallback((t) {
                setState(() {
                  activeTextIndex += 1;
                });
              });
            }
          }
    
          return Text.rich(
            textSpan,
            overflow: TextOverflow.ellipsis,
            maxLines: 1,
          );
        });
      }
    }
    

    Our OverflowAwareText takes a parameter alternativeTexts which is List<String>. You have to provide a list of Strings with larger to smaller values.

    We can now use the OverflowAwareText :

    @override
      Widget build(BuildContext context) {
        print('Printing from build method');
        return Scaffold(
          body: Center(
            child: Container(
              alignment: Alignment.center,
              height: 50,
              color: Colors.amber,
              child: OverflowAwareText(
                alternativeTexts: [
                  'Kamala Devi Harris',
                  'K. D. Harris',
                  'K. Harris',
                  'K. H'
                ],
              ),
            ),
          ),
        );
      }
    

    We've wrapped the OverflowAwareText in a Container, so that we can check if the text is being changed or not when there is less space.

    RESULT :

    enter image description here

    enter image description here

    enter image description here

    With width = 100 in Container

    enter image description here