Files
Bahla-Front/lib/ui/common/ReadMoreText.dart
2025-09-02 19:16:40 +02:00

100 lines
3.0 KiB
Dart

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
class ReadMoreText extends StatefulWidget {
const ReadMoreText(
this.text, {
Key? key,
this.trimLines = 2,
this.collapsedText = '... read more',
this.expandedText = ' read less',
this.textStyle,
}) : assert(text != null),
super(key: key);
final String text;
final int trimLines;
final String collapsedText;
final String expandedText;
final TextStyle? textStyle;
@override
ReadMoreTextState createState() => ReadMoreTextState();
}
class ReadMoreTextState extends State<ReadMoreText> {
bool _readMore = true;
void _onTapLink() {
setState(() => _readMore = !_readMore);
}
@override
Widget build(BuildContext context) {
final DefaultTextStyle defaultTextStyle = DefaultTextStyle.of(context);
final colorClickableText = Colors.blue;
final widgetColor = Colors.black;
TextSpan link = TextSpan(
text: _readMore ? widget.collapsedText : widget.expandedText,
style: TextStyle(
color: colorClickableText,
),
recognizer: TapGestureRecognizer()..onTap = _onTapLink
);
Widget result = LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
assert(constraints.hasBoundedWidth);
final double maxWidth = constraints.maxWidth;
// Create a TextSpan with data
final text = TextSpan(
text: widget.text,
);
// Layout and measure link
TextPainter textPainter = TextPainter(
text: link,
textDirection: TextDirection.rtl,//better to pass this from master widget if ltr and rtl both supported
maxLines: widget.trimLines,
ellipsis: '...',
);
textPainter.layout(minWidth: constraints.minWidth, maxWidth: maxWidth);
final linkSize = textPainter.size;
// Layout and measure text
textPainter.text = text;
textPainter.layout(minWidth: constraints.minWidth, maxWidth: maxWidth);
final textSize = textPainter.size;
// Get the endIndex of data
int? endIndex;
final pos = textPainter.getPositionForOffset(Offset(
textSize.width - linkSize.width,
textSize.height,
));
endIndex = textPainter.getOffsetBefore(pos.offset);
var textSpan;
if (textPainter.didExceedMaxLines) {
textSpan = TextSpan(
text: _readMore
? widget.text.substring(0, endIndex)
: widget.text,
style: widget.textStyle ?? TextStyle(
color: widgetColor,
),
children: <TextSpan>[link],
);
} else {
textSpan = TextSpan(
text: widget.text,
style: widget.textStyle ?? TextStyle(
color: widgetColor,
),
);
}
return RichText(
softWrap: true,
overflow: TextOverflow.clip,
text: textSpan,
);
},
);
return result;
}
}