如果文本溢出则替换文本

时间:2018-06-03 02:23:43

标签: text flutter flutter-layout

我想知道如果原始文字会溢出,Flutter是否有办法显示替代文字。

示例:

我默认显示完整日期:January 1, 2019

但是,如果我在小屏幕上并且会溢出(January 1...),我想改为显示不同的字符串(1/1/2019)。

4 个答案:

答案 0 :(得分:3)

当前Text实现不允许这种逻辑。您需要使用自定义溢出逻辑覆盖它们的实现。

修改是微不足道的,但请记住,如果发生溢出,你实际上是在两次计算文本。

修改需要在RenderParagraph的{​​{1}}内完成。

简而言之,就像这样:

performLayout

然后需要自定义performLayout() layout(); if (overflow) { layoutWithText(text); } } 才能使用新的RichText。然后是新的RenderParagraph课程,以使用新的Text

相当多的复制粘贴。但幸运的是我会为你做的:D

以下是两次渲染相同RichText的示例。一旦没有足够的尺寸,另一个没有限制。

enter image description here

使用以下代码实现:

Super long text

这是完整的工作示例(new Column( crossAxisAlignment: CrossAxisAlignment.center, mainAxisSize: MainAxisSize.min, children: <Widget>[ new SizedBox( width: 70.0, child: new Card( child: new MyText( "Super long text", maxLines: 1, overflowBuilder: (size) { return new TextSpan( text: "Hello", style: new TextStyle(color: Colors.red)); }, ), ), ), new Card( child: new MyText( "Super long text", maxLines: 1, overflowBuilder: (size) { return new TextSpan( text: "Hello", style: new TextStyle(color: Colors.red)); }, ), ), ], ); 更改和内容)

RenderParagraph

答案 1 :(得分:1)

这是一个比Remi看起来更简单(或至少更短)的解决方案。

想法是使用LayoutBuilder包装小部件,从而获得BoxConstraints,然后使用TextPainter来确定文本是否是否适合给定的BoxConstraints。

这是一个有效的示例:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Text Overflow Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(title: Text("DEMO")),
        body: TextOverflowDemo(),
      ),
    );
  }
}

class TextOverflowDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    int maxLines = 1;

    return Container(
      color: Colors.white,
      child: ConstrainedBox(
        constraints: const BoxConstraints(maxWidth: 60.0),// set maxWidth to a low value to see the result
        child: LayoutBuilder(builder: (context, size) {
          String text = 'January 1, 2019';
          var exceeded = doesTextFit(text, maxLines, size);

          return Column(children: <Widget>[
            Text(
              exceeded ? '1/1/2019' : text,
              overflow: TextOverflow.ellipsis,
              maxLines: maxLines,
            ),
          ]);
        }),
      ),
    );
  }

  bool doesTextFit(String text, int maxLines, BoxConstraints size,
      {TextStyle textStyle}) {
    TextSpan span;
    if (textStyle == null) {
      span = TextSpan(
        text: text,
      );
    } else {
      span = TextSpan(text: text, style: textStyle);
    }

    TextPainter tp = TextPainter(
      maxLines: maxLines,
      textAlign: TextAlign.left,
      textDirection: TextDirection.ltr,
      text: span,
    );

    tp.layout(maxWidth: size.maxWidth);

    return tp.didExceedMaxLines;
  }
}

答案 2 :(得分:1)

我最终得到了一个由@Mantoska的答案启发的解决方案。

import 'package:flutter/widgets.dart';

class OverflowProofText extends StatelessWidget {
  const OverflowProofText({@required this.text, @required this.fallback});

  final Text text;
  final Text fallback;

  @override
  Widget build(BuildContext context) {
    return SizedBox(
        width: double.infinity,
        child: LayoutBuilder(builder: (BuildContext context, BoxConstraints size) {
          final TextPainter painter = TextPainter(
            maxLines: 1,
            textAlign: TextAlign.left,
            textDirection: TextDirection.ltr,
            text: TextSpan(
                style: text.style ?? DefaultTextStyle.of(context).style,
                text: text.data
            ),
          );

          painter.layout(maxWidth: size.maxWidth);

          return painter.didExceedMaxLines ? fallback : text;
        })
    );
  }
}

用法:

OverflowProofText(
  text: Text('January 1, 2019'),
  fallback: Text('1/1/2019', overflow: TextOverflow.fade),
),

答案 3 :(得分:0)

我为仍在寻找的人们找到了一个更简单的解决方案。 我在包装上建立了解决方案:auto_size_text 2.1.0

import 'package:auto_size_text/auto_size_text.dart';
...
AutoSizeText(
    "Your text that might be too long. I'm super duper long",
    maxLines: 1,
    overflowReplacement: Text("I'm the new (small) replacement!"),
    // minFontSize: 20
),

请注意,在触发overflowReplacement之前,此程序包还将使文本变小。您可以通过指定minFontSize来设置包中允许的最小大小。