flutter - 在 Flutter 中扩展 RichText
问题描述
Message
Widget 返回一个以 RichText Widget 作为子级的 Container 。如果 RichText 的内容超过某个预定义的限制(例如 100 个字符),我想添加尾随文本“阅读更多”,因此当点击“阅读更多”时它会扩展。我遇到了这篇关于将 CustomPainter 与 TextSpan 结合使用的中型文章。我需要 RichText 类似的东西。
class Message extends StatelessWidget {
final Widget _content;
Message()
: this._content = Content(),
super(key: key);
@override
Widget build(BuildContext context) {
...
return new Container(
child: _content,
);
}
class Content extends StatelessWidget {
@override
Widget build(BuildContext context) {
List<TextSpan> parsedText = createTextSpan(...);
return RichText(
text: TextSpan(children: parsedText),
);
}
解决方案
工作示例:
class ExpandableText extends StatefulWidget {
final String text;
final int trimLines;
final TextStyle style;
const ExpandableText(
this.text, {
Key key,
this.trimLines = 2,
this.style,
}) : assert(text != null),
super(key: key);
@override
ExpandableTextState createState() => ExpandableTextState();
}
class ExpandableTextState extends State<ExpandableText> {
bool _readMore = true;
void _onTapLink() {
setState(() => _readMore = !_readMore);
}
@override
Widget build(BuildContext context) {
TextSpan link = TextSpan(
text: _readMore
? '... Read more'
: ' Read less',
style: TextStyle(
color: Colors.blue,
),
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,
style: widget.style,
);
// 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.style,
children: <TextSpan>[link],
);
} else {
textSpan = TextSpan(
text: widget.text,
style: widget.style,
);
}
return RichText(
softWrap: true,
overflow: TextOverflow.clip,
text: textSpan,
);
},
);
return result;
}
}
推荐阅读
- php - 如果数字有内部数字字符串
- pandas - 在 numpy 中实现自定义矩阵乘法运算
- java - Java Runtime.exec 在字符串中转义了参数
- jsp - The server cannot started because one or more of the ports are invalid [Tomcat in Eclipse]
- java - Spring Data JPA conditional entity join
- c++ - How to build openFrameworks as a shard library on macOS
- shell - Does opening a pipeline in Perl involve a shell?
- jquery - 如何使用 jquery 从滑块中获取值
- ansible - 使用 KeyCtl 和嵌套在 Proxmox 上创建 LXC 容器
- iso8601 - In ISO 8601 does 'P1D' mean midnight tonight? 24 hours from now? Midnight tomorrow night?