1.说明
Flutter支持在文本末尾
显示溢出省略号。现在想要实现在文本中间位置显示省略号,这里使用的方法是通过TextPainter计算文本宽度
。(我目前没有找到更好的方法,欢迎大家指教。)
2.效果
源码
1.MiddleEllipsisTextPainter
class MiddleEllipsisTextPainter extends CustomPainter {
final String text;
final TextStyle textStyle;
final double maxWidth;
MiddleEllipsisTextPainter({
required this.text,
required this.textStyle,
required this.maxWidth,
});
void paint(Canvas canvas, Size size) {
TextPainter textPainter = TextPainter(
textDirection: TextDirection.ltr,
text: TextSpan(text: text, style: textStyle),
maxLines: 1)
..layout(maxWidth: double.infinity);
// print("textPainter.width = ${textPainter.width}");
if (textPainter.width <= maxWidth) {
print("📢 文本长度没有超过 maxWidth , 直接绘制");
textPainter.paint(canvas, Offset.zero);
} else {
print("📢 😔 文本长度超过了 maxWidth , 在中间添加省略号");
// 如果直接选取中间的位置展示省略号,那么很有可能后半段文案没有完整展示。
// 替换方案:后半段限制最多的字符
int lastMaxLength = 8;
int splitPos = min(text.length - lastMaxLength, lastMaxLength).abs();
String firstPart = text.substring(0, splitPos);
String lastPart = text.substring(text.length - splitPos);
String middlePart = '...';
// 尾部
TextPainter lastPainter = TextPainter(
textDirection: TextDirection.ltr,
text: TextSpan(text: lastPart, style: textStyle),
maxLines: 1)
..layout(maxWidth: maxWidth);
// 省略号
TextPainter middlePainter = TextPainter(
textDirection: TextDirection.ltr,
text: TextSpan(text: middlePart, style: textStyle),
maxLines: 1)
..layout(maxWidth: maxWidth);
// 前半截
TextPainter firstPainter = TextPainter(
textDirection: TextDirection.ltr,
textAlign: TextAlign.end,
text: TextSpan(text: firstPart, style: textStyle),
maxLines: 1)
..layout(maxWidth: maxWidth - middlePainter.width - lastPainter.width);
// 从最左边开始绘制
double startX = 0;
firstPainter.paint(canvas, Offset(startX, 0));
middlePainter.paint(canvas, Offset(startX + firstPainter.width, 0));
lastPainter.paint(
canvas, Offset(startX + firstPainter.width + middlePainter.width, 0));
}
}
bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}
2.UI部分
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: 200,
height: 40, // 设置一个足够容纳一行文本的高度
color: Colors.grey.shade200,
child: CustomPaint(
size: const Size(200, 40),
painter: MiddleEllipsisTextPainter(
text: '这可能导致路径错误或无法找到文件.mp3',
textStyle: const TextStyle(fontSize: 16, color: Colors.black),
maxWidth: 200,
),
),
),
const SizedBox(
height: 20,
),
Container(
width: 200,
height: 40, // 设置一个足够容纳一行文本的高度
color: Colors.grey.shade200,
child: CustomPaint(
size: const Size(200, 40),
painter: MiddleEllipsisTextPainter(
text: 'Recording_1_long_long_long.wav',
textStyle: const TextStyle(fontSize: 16, color: Colors.black),
maxWidth: 200,
),
),
)
],
)