【问题标题】:How to dynamically resize text in Flutter?如何在 Flutter 中动态调整文本大小?
【发布时间】:2018-11-17 23:01:00
【问题描述】:

我从 API 检索一段文本。我想为其分配一定数量的空间(比如一个最大容器,宽度:300.0,高度:100.0)。有时,该文本适合此 Container,字体大小为 30.0。在其他时候,除非我将文本大小设置为 24.0,否则它不适合。

有没有办法根据其父容器空间动态调整文本大小?

我已经构建了一个带有 ConstrainedBox 的容器,它可以让我定义文本空间的最大大小。我还用 LayoutBuilder 包装了我的文本。我希望我可以检查文本空间的高度,并在此基础上确定如何调整文本的大小。像这样:

    Container(
      child: ConstrainedBox(
        constraints: BoxConstraints(
          minWidth: 300.0,
          maxWidth: 300.0,
          minHeight: 30.0,
          maxHeight: 100.0,
        ),
        child: LayoutBuilder(
            builder: (BuildContext context, BoxConstraints constraints) {
          if (/* height is larger than 100.0? height is over the constraints? */) { return textWithSize24(); }
          return textWithSize30();
        }),
      ),
    ),

如何确定“如果文本大小为 30.0,文本将占据的高度”? 也许我以错误的方式接近这个问题,我应该使用maxLines 来确定这个?但是我们怎么知道我们已经达到了超过maxLines

另一种方法是使用我的字符串中的字符数来确定何时更改字体大小。这似乎有点手动。

【问题讨论】:

标签: flutter


【解决方案1】:

您可以使用FittedBox 来管理基于高度或宽度的文本。

例如

只需将 Text 小部件包装到 FittedBox 小部件,例如,我想根据宽度调整 AppBar 文本的大小。

AppBar(
    centerTitle: true,
    title: FittedBox(
        fit: BoxFit.fitWidth, 
        child: Text('Hey this is my long text appbar title')
    ),
),

文本将根据 AppBar 的宽度调整大小。

【讨论】:

  • 工作起来就像一个魅力,很棒的解决方案。
  • 我发现我的文字被强制填满了方框。有没有办法用这种方法限制最大字体大小?
  • @louisdeb 我遇到了同样的问题,请改用github.com/leisim/auto_size_text。更灵活
  • @louisdeb 我有一个简单的解决方案。 stackoverflow.com/a/63124491/12661107 你可以使用 BoxFit.scaleDown 来限制文本大小。
  • 您能否分享您遇到困难的代码以及您的要求,因为这适用于我们所有人。(需要查看您的要求,因为有时会发生)跨度>
【解决方案2】:

您可以使用auto_size_text 包来做到这一点:

Container(
  child: ConstrainedBox(
    constraints: BoxConstraints(
      minWidth: 300.0,
      maxWidth: 300.0,
      minHeight: 30.0,
      maxHeight: 100.0,
    ),
    child: AutoSizeText(
      "yourText",
      style: TextStyle(fontSize: 30.0),
    ),
  ),
);

您还可以设置maxLines 以进一步限制文本,或者如果您只想允许特定的字体大小,请使用presetFontSizes

【讨论】:

  • 很棒的插件!谢谢你:)
  • 这个比 FittedBox 更灵活
  • 这个包不错。但是面对这个问题:切入生成的字符串github.com/leisim/auto_size_text/issues/64
  • NOO。不要使用它。它有很多错误。改用 FittedBox
  • 它也不支持可选文本 afaik。如果可能,将 FittedBox 与 BoxFit.scaleDown 一起使用。
【解决方案3】:

使用BoxFit.scaleDown 并修复FontSize 可以调整字体的最大大小。

如果内容很小,则占用指定字体大小的最小宽度。同时,如果内容较大,则调整为最小字体大小。

FittedBox(
                      fit: BoxFit.scaleDown,
                      child: 
                          Text(
                            "Text here",
                            style: TextStyle(fontSize: 18),
                          ),)

如果您需要文字填满整个宽度,请使用任何字体大小使用BoxFit.cover

FittedBox(
                      fit: BoxFit.cover,
                      child: 
                          Text(
                            "Text here",
                            //style: TextStyle(fontSize: 18),
                          ),)

【讨论】:

  • 嘿,这个非常适合单行文本框。如果我想要一个跨越多行的文本小部件,我应该怎么做?
【解决方案4】:

FittedBox 在我的案例中使用多行。

SizedBox(
            width: MediaQuery.of(context).size.width,
            child: FittedBox(
              fit: BoxFit.contain,
              child: Text(
                widget.model.poem,
                textAlign: TextAlign.justify,
                style: TextStyle(
                    color: Colors.black,
                    fontWeight: FontWeight.w600,
                    fontStyle: FontStyle.normal),
              ),
            ),
          ),

【讨论】:

    【解决方案5】:

    以下是我尝试过的方法列表,根据您的用例可能对您有用:https://github.com/flutter/flutter/issues/18431

    最后,我使用了一个根据字符串长度设置字体大小的函数(即使用 if-else 语句)。

    【讨论】:

      【解决方案6】:

      Responsive_Flutter,自从阅读了您的问题后,我遇到了同样的问题。我发现它每次都有效使用这个包来调整你的字体。

      此 Flutter 包用于在不同尺寸的设备上缩放应用 UI 和 fontSize 的大小。 (示例显示使用 Responsive_Flutter 包的顶部文本和不使用插件的底部文本。

      https://github.com/layounisl/responsive_flutter

      您可以在 30 秒内安装 - 3 个步骤

      1. 添加依赖到yaml文件responsive_flutter: ^0.0.4
      2. import 'package:responsive_flutter/responsive_flutter.dart';
      3. child: Text("Responsive flutter", style: TextStyle(fontSize: ResponsiveFlutter.of(context).fontSize(3)),

      【讨论】:

        【解决方案7】:

        只根据文字长度和最大渲染区域生成字体大小。 300.0 * 100.0 在你的情况下,不要忘记在文本渲染过程中丢失的区域。

        像这样:

        class MyWidget extends StatefulWidget {
          @override
          _StateMyWidget createState() => _StateMyWidget();
        }
        
        class _StateMyWidget extends State<MyWidget> {
          static const _QUOTES = [
            {"quote": "mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm", "author": "test"},
            {"quote": "Talk is cheap. Show me the code.", "author": "Linus Torvalds"},
            {"quote": "First, solve the problem. Then, write the code.", "author": "John Johnson"},
            {"quote": "To iterate is human, to recurse divine.", "author": "L. Peter Deutsch"},
            {"quote": "The best thing about a boolean is even if you are wrong, you are only off by a bit.", "author": "Anonymous"},
            {"quote": "Software is like sex: It’s better when it’s free.", "author": "Linus Torvalds"},
            {"quote": "The first 90% of the code accounts for the first 90% of the development time.  The remaining 10% of the code accounts for the other 90% of the development time.", "author": "Tom Cargill"},
            {"quote": "I think that it’s extraordinarily important that we in computer science keep fun in computing. When it started out it was an awful lot of fun. Of course the paying customers got shafted every now and then and after a while we began to take their complaints seriously. We began to feel as if we really were responsible for the successful error-free perfect use of these machines. I don’t think we are. I think we’re responsible for stretching them setting them off in new directions and keeping fun in the house. I hope the field of computer science never loses its sense of fun. Above all I hope we don’t become missionaries. Don’t feel as if you’re Bible sales-men. The world has too many of those already. What you know about computing other people will learn. Don’t feel as if the key to successful computing is only in your hands. What’s in your hands I think and hope is intelligence: the ability to see the machine as more than when you were first led up to it that you can make it more.", "author": "Alan J. Perlis"},
            {"quote":"Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live","author": "John Woods"},
            {"quote":"You've baked a really lovely cake, but then you've used dog shit for frosting.","author": "Steve Jobs"},
            {"quote": "Most software today is very much like an Egyptian pyramid with millions of bricks piled on top of each other, with no structural integrity, but just done by brute force and thousands of slaves.","author": "Alan Kay" },
            {"quote": "Software suppliers are trying to make their software packages more ‘user-friendly’…  Their best approach so far has been to take all the old brochures and stamp the words ‘user-friendly’ on the cover.","author": "Bill Gates"},
          ];
        
          static const AREA_LOST_PERCENT = 5;
        
          final rand = math.Random();
        
          @override
          initState() {
            super.initState();
            Timer.periodic(Duration(seconds: 3), (timeVal) {
              setState(() {});
            });
          }
        
          @override
          Widget build(BuildContext context) {
            final Map<String, String> mapQuote = _QUOTES[rand.nextInt(_QUOTES.length)];
        
            final authorW =
                Text(mapQuote["author"], style: TextStyle(fontStyle: FontStyle.italic));
        
            final quoteW = Text(
              mapQuote["quote"],
              textAlign: TextAlign.center,
              style: TextStyle(
                fontSize: autoSize(
                  quoteLength: mapQuote["quote"].length,
                  parentArea: (350 - 10 * 2 - 16 * 2) * (450 - 10 * 2),
                ),
              ),
            );
        
            final containerW0 = Container(
                height: 450.0,
                padding: EdgeInsets.all(10.0),
                color: Colors.grey,
                child: Center(child: quoteW));
        
            final containerW1 = Container(
                height: 500.0,
                width: 350,
                padding: EdgeInsets.all(16.0),
                color: Colors.purple,
                child: Column(children: [authorW, containerW0]));
        
            return containerW1;
          }
        
          double autoSize({@required int quoteLength, @required int parentArea}) {
            assert(quoteLength != null, "`quoteLength` may not be null");
            assert(parentArea != null, "`parentArea` may not be null");
            final areaOfLetter = parentArea / quoteLength;
            final pixelOfLetter = math.sqrt(areaOfLetter);
            final pixelOfLetterP = pixelOfLetter - (pixelOfLetter * AREA_LOST_PERCENT) / 100;
            return pixelOfLetterP;
          }
        }
        

        在分配丢失区域的百分比时必须考虑转义字符。如果变化过大,最好将其删除。

        Online view -> dartpad.dev

        【讨论】:

          【解决方案8】:

          有两种方法可以做到这一点。

          1. 使用 FittedBox
          2. 使用 TextPainter(使用文本 Painter 计算宽度 并更新字体)

          https://prafullkumar77.medium.com/how-to-dynamically-resize-text-in-flutter-bca80415a4d2

          【讨论】:

            【解决方案9】:

            我找到的最简单的东西是auto_size_text: ^2.1.0。就像导入依赖并使用AutoSizeText()而不是Text()一样简单

            import 'package:auto_size_text/auto_size_text.dart';
            import 'package:flutter/material.dart';
            
            void main() {
              runApp(App());
            }
            
            class App extends StatelessWidget {
              @override
              Widget build(BuildContext context) {
                return MaterialApp(
                  home: Scaffold(
                    body: Center(
                      child: SizedBox(
                        width: 200.0,
                        height: 140.0,
                        child: AutoSizeText(
                          'This string will be automatically resized to fit in two lines.',
                          style: TextStyle(fontSize: 30.0),
                          maxLines: 2,
                        ),
                      ),
                    ),
                  ),
                );
              }
            }
            

            【讨论】:

            • autosizetext 有很多错误
            【解决方案10】:

            您还可以使用MediaQueryData 类中的textScaleFactor 属性来限制文本的大小

            【讨论】:

            • 文本缩放因子属性,顾名思义,允许您缩放字体大小,而不是限制它!
            猜你喜欢
            • 2010-09-21
            • 1970-01-01
            • 2021-06-01
            • 2021-01-17
            • 2020-03-03
            • 2018-07-14
            • 2011-06-12
            • 1970-01-01
            • 2014-09-25
            相关资源
            最近更新 更多