【问题标题】:How do I auto scale down a font in a Text widget to fit the max number of lines?如何自动缩小文本小部件中的字体以适应最大行数?
【发布时间】:2018-05-19 18:58:51
【问题描述】:

我正在尝试在 FittedBox 的 fit 属性中使用 BoxFit.scaleDown 来缩小 Text 小部件中的字体以适应不同长度的字符串。

但是,下面的代码将缩小整个字符串并使其适合一行,对于下面的示例,我希望缩小字体以便字符串可以适合两行(根据 maxLines 的属性Text 小部件)。

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Multi-Line Label Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new MyHomePage(title: 'Multi-Line Label Demo'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    final textStyle = const TextStyle(fontSize: 28.0);
    final text =
        'Lorem Ipsum is simply dummy text of the printing and typesetting'
        'industry. Lorem Ipsum has been the industry\'s standard dummy text'
        'ever since the 1500s, when an unknown printer took a galley of type'
        'and scrambled it to make a type specimen book.';
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(widget.title),
      ),
      body: new Center(
        child: new Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            new FittedBox(
              fit: BoxFit.scaleDown,
              child: new Text(
                text,
                maxLines: 2,
                style: textStyle,
                textAlign: TextAlign.center,
              ),
            ),
          ],
        ),
      ),
    );
  }
}

【问题讨论】:

  • 你想在哪里换行?
  • 我认为任何地方都可以,只要文本扩展为使用最大行数。
  • maxLines 是否适合您?它始终显示在带有拟合框的单行中

标签: dart flutter


【解决方案1】:

一个简单的解决方案是使用FittedBox 和fit: BoxFit.scaleDown:

Container(
  width: 100.0,
  child: FittedBox(
    fit: BoxFit.scaleDown,
    // Optionally apply `alignment` to position the text inside the box:
    //alignment: Alignment.topRight,
    child: SizedBox(
      child: Text('\$1,299.99'),
  )
)

【讨论】:

    【解决方案2】:

    你可以使用自动文本包

    https://pub.dartlang.org/packages/auto_size_text

    安装后,只需将所有 'Text' 替换为 'AutoSizeText',你会发现一切都会好起来的 :)

    【讨论】:

    • 我同意 AutoSizeText 是最好的答案,但绝对不是“将所有 'Text' 替换为 'AutoSizeText' ”那么简单。您需要在 TextStyle(fontSize: 30.0) 中选择理想的字体大小,然后使用 AutoSizeText,您需要使用“minFontSize:”来选择文本可以走多小,然后使用“maxLines:”来确定数量溢出你的文本是允许的。包站点提供的功能显然更多,但我觉得这个答案至少应该提供一个例子。
    • 无插件解决方案-stackoverflow.com/a/67651675/7857541
    【解决方案3】:

    根据您想要的限制条件,我们有 2 个现成的解决方案。

    1。仅缩放

    如果您喜欢布局在某个参考屏幕尺寸上的外观,希望将文本区域视为一个框,并在给定其他尺寸的屏幕时放大或缩小整个框,则此解决方案有效。

    获取参考屏幕。按预期布置一切。找出包含文本的框的大小(例如,通过在调试期间按“t”显示渲染树)。然后用与测量大小相同的SizedBox 包裹包含文本的框。然后用你的FittedBox 包装它。

    限制基本上是您的文本在所有屏幕上的布局方式完全相同,并且您的文本框将具有相同的纵横比。

    2。多个参考

    给定一个大小可变的父级,首先使用LayoutBuilder 在运行时获取父级的大小,然后手动调整子文本小部件中的字体大小以确保其适合。

    文本布局更加流畅,包含框可以有不同的纵横比,但您必须检查与您拥有的字体大小开关一样多的屏幕尺寸。尽管使用widget tests 很容易确保文本在任何屏幕尺寸下都不会溢出


    如果有更多涉及依赖字体缩放的通用用例的具体示例,我们还可以创建更复杂但自动的方法

    【讨论】:

    • 似乎使用 SizedBox 意味着如果文本很短(例如 3 个字符而不是两行),则无法删除框中的多余空间。例如。如果我只想使用尽可能多的行来呈现文本。
    【解决方案4】:

    这发生在我的应用程序中:

    我通过计算一行中显示的最大字符数来解决,如果它的字符串长度更大,则动态减小 Text FontSize。

    获取文本的字符宽度

    首先,我计算了显示的每个字符的宽度。 为此,我需要有效的容器宽度和显示的字符数。 为了获得屏幕宽度(实际上是容器宽度),我将 Text 小部件放在 LayoutBuilder 中:

    new LayoutBuilder(builder: (context, constraint) {
       //screen width got from the LayoutBuilder
       double maxWidth = constraint.biggest.width;
    
       //I'm going to change this dinamically
       double fontSize = 33.0;
    
       //return my widget
       return new Text(
            _brand.name,
            maxLines: 1,
            style: new TextStyle(fontSize: fontSize),
        );
    }
    

    为了在新行之前显示字符,我在 Text 中放了一个大字符串,然后我手动计算了一行中显示了多少个字符。我把这个值放在一个 const (maxCharInOneLine) 中,然后我就能计算出单个字符的宽度:我将最大宽度除以 maxCharInOneLine:

    new LayoutBuilder(builder: (context, constraint) {
       //screen width got from the LayoutBuilder
       double maxWidth = constraint.biggest.width;
    
       //chars shown manually counted
       const int maxCharInOneLine = 17;
       
       //single char width
       int charWidth = (maxWidth / maxCharInOneLine).toInt();
       
       //TO RUN IN DEBUG MODE
       print("Char size with this screen and Text's TextStyle: " + charWidth.toString());
       ...
    }
    

    我在调试模式下运行上面的代码以获得charSize 值,然后我将 is 放入一个 const 中,并删除了在运行时无用的代码。

    动态更改字体

    现在,使用恒定的字符宽度和可变的容器宽度(从 LayoutBuilder 获得),您每次都可以获得适合一行的最大字符数。

    new LayoutBuilder(builder: (context, constraint) {
        const int charWidth=16;
        //screen width got from the LayoutBuilder
        double maxWidth = constraint.biggest.width;
    
        //dinamically get the char number that fits in one line with this screen
        int charsPerLine = (maxWidth / charWidth).toInt();
    
        //if it doesn't fit in a line, reduce the fontSize
        double fontSize = (_brand.name.length <= charsPerLine) ? 33.0 : 23.0;
    
        return new Text(
            _brand.name,
            maxLines: 1,
            style: new TextStyle(fontSize: fontSize),
        );
    }
    

    结果:

    我的解决方案不是最好的,但在我的情况下效果很好。

    我想获得反馈。 :)

    2020 年 8 月编辑:您现在可以简单地使用库 AutoSizeText

    【讨论】:

      【解决方案5】:

      只需将您的Text 包装在FittedBox 小部件中,而无需设置任何fit 值。

      SizedBox(
        width: 10,
        child: FittedBox(
          child: Text('Your Text'),
        ),
      )
      

      【讨论】:

        【解决方案6】:

        您是否尝试过使用灵活小部件

        new Flexible(
          child: new Text(
            text,
            style: textStyle,
            textAlign: TextAlign.center,
          ),
        ),
        

        【讨论】:

          猜你喜欢
          • 2014-04-18
          • 1970-01-01
          • 1970-01-01
          • 2017-02-08
          • 2012-04-12
          • 1970-01-01
          • 2011-05-23
          • 2022-01-03
          • 2017-12-24
          相关资源
          最近更新 更多