You can configure the overflow as you like... and from how many lines you want the view more button to appear.
Component demo:
Code:Example
class AppExpandableText extends StatefulWidget {
final String text;
final TextStyle? style;
final int trimLines;
const AppExpandableText({
super.key,
required this.text,
this.style,
this.trimLines = 3,
});
@override
State<AppExpandableText> createState() => _AppExpandableTextState();
}
class _AppExpandableTextState extends State<AppExpandableText> {
bool _expanded = false;
bool _isOverflowing = false;
@override
void didChangeDependencies() {
super.didChangeDependencies();
WidgetsBinding.instance.addPostFrameCallback((_) => _checkOverflow());
}
void _checkOverflow() {
final span = TextSpan(text: widget.text, style: widget.style);
final tp = TextPainter(
text: span,
maxLines: widget.trimLines,
textDirection: TextDirection.ltr,
)..layout(maxWidth: MediaQuery.of(context).size.width);
setState(() {
_isOverflowing = tp.didExceedMaxLines;
});
}
@override
Widget build(BuildContext context) {
final textWidget = Text(
widget.text,
style: widget.style,
maxLines: _expanded ? null : widget.trimLines,
overflow: _expanded ? TextOverflow.visible : TextOverflow.clip,
);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
textWidget,
if (_isOverflowing)
InkWell(
onTap: () => setState(() => _expanded = !_expanded),
child: Text(
_expanded ? '...Ver menos' : '...Ver más',
style: widget.style,
),
),
],
);
}
}