Flutter:如何获取文本行数

Flutter: How to Get the Number of Text Lines

如何获取文本行数 在我们的Flutter项目中,我们需要判断文本的行数是否超过3,然后我们会显示一个提示信息。我们如何使用代码来实现它?

如果你只是想知道文本包含多少行,你可以做一个简单的

final numLines = '\n'.allMatches(yourText).length + 1;

不过,我猜您更感兴趣的是实际在视觉上显示的行数。 在这里,事情变得有点复杂,因为您需要知道可用的 space(BoxConstraints)才能计算文本需要多少行。 为此,您可以使用 LayoutBuilder 来延迟小部件构建,并使用 TextPainter 来进行实际计算:

return LayoutBuilder(builder: (context, constraints) {
  final span = TextSpan(text: yourText, style: yourStyle);
  final tp = TextPainter(text: span);
  tp.layout(maxWidth: constraints.maxWidth);
  final numLines = textPainter.computeLineMetrics().length;

  if (numLines > 3) {
    // TODO: display the prompt message
    return ColoredBox(color: Colors.red);
  } else {
    return Text(yourText, style: yourStyle);
  }
});

我从 auto_size_text pub package 中提取了一些代码,您可能也会感兴趣: 它调整其文本的大小,使其适合给定的 space.

总之,显示提示时要小心: 您的小部件的 build 方法可能每秒被调用多次,导致同时显示多个提示。

注:computeLineMetrics()功能是在最初版本的回答后添加的。这就是为什么此答案的先前版本使用 TextPainter(text: span, maxLines: 3) 然后检查是否 tp.didExceedMaxLines.

更新:这个答案是为了历史目的。请参阅 以获得更简单的解决方案。


如果您有一个 TextPainter 对象并且您已经调用了 layout,那么您可以通过选择所有内容并调用 getBoxesForSelection 来获取行数。每个方框都是线的大小。

TextSelection selection = TextSelection(baseOffset: 0, extentOffset: text.length);
List<TextBox> boxes = textPainter.getBoxesForSelection(selection);
int numberOfLines = boxes.length;

这是一个例子:

final text = 'My text line.\nThis line wraps to the next.\nAnother line.';

print(numberOfLines); // 4

不幸的是,如果存在双向文本混合,此操作将失败:

final text = 'My text line.\nThis كلمة makes more boxes.\nAnother line.';

print(numberOfLines); // 6

这可以通过仅计算沿着一条边的框来解决。如果您注意到上面的数据,只有四个框的边为 0.0。

flutter: TextBox.fromLTRBD(0.0, 0.2, 171.8, 36.0, TextDirection.ltr)
flutter: TextBox.fromLTRBD(0.0, 36.5, 68.4, 72.3, TextDirection.ltr)
flutter: TextBox.fromLTRBD(68.4, 38.2, 111.5, 75.0, TextDirection.rtl)
flutter: TextBox.fromLTRBD(111.5, 36.5, 299.9, 72.3, TextDirection.ltr)
flutter: TextBox.fromLTRBD(0.0, 77.2, 92.2, 113.0, TextDirection.ltr)
flutter: TextBox.fromLTRBD(0.0, 113.2, 179.7, 149.0, TextDirection.ltr)

我希望有一个 TextPainter.numberOfLines 方法,但我没有找到它。

现在很容易找到一个段落中的行数:

List<ui.LineMetrics> lines = textPainter.computeLineMetrics();
int numberOfLines = lines.length;

备注

  • computeLineMetrics必须在布局后调用。
  • 我保留了另一个答案以供历史参考,因为我需要 link 解释更改。

另见

我刚得到这段代码的支持,因此这就是我验证它是否超过最大线数的方式

var text="Clita takimata dolor diam magna aliquyam et sed dolores sadipscing. Sed ut 
diam rebum labore sadipscing sit amet, diam labore.";
final span=TextSpan(text:text);
final tp =TextPainter(text:span,maxLines: 3,textDirection: TextDirection.ltr);
tp.layout(maxWidth: MediaQuery.of(context).size.width); // equals the parent screen width
print(tp.didExceedMaxLines);
//false for maxlines 3
//true for maxlines 1

在我的例子中,我需要获取行数以根据它更改高度,但我使用 Stack 小部件作为解决方法。 这是我的代码:

                   Container(
                    height: AppTheme.fullHeight(context) *.08,
                    child: Stack(
                      children: [
                        Container(
                          height: AppTheme.fullHeight(context) *.08,
                          child: Text(
                            "${products[index].name!}",
                            maxLines: 2,
                            overflow: TextOverflow.ellipsis,
                            style: TextStyle(fontSize: 12,color: Utils.secondaryColor),),
                        ),
                        //SizedBox(height: MediaQuery.of(context).size.height * .01,),
                        Positioned(
                          bottom: AppTheme.fullHeight(context) *.0,
                          left: 0,
                          child: Text(
                            products[index].price! + Constants.CURRENCY.tr,
                            style: TextStyle(fontSize: 16,
                                fontWeight: FontWeight.bold,color: Utils.secondaryColor),),
                        )
                      ],
                    ),
                  ),

只需放置 属性 maxLines: null 和 TextInputAction.done,如果您想将新行限制为特定的限制计数 "\n" 。