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?
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 :
Container
width = 330
in Container
width = 180
in Container
With width = 100
in Container