如何自动缩小文本小部件中的字体以适应最大行数?

时间:2017-12-06 00:50:33

标签: dart flutter

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

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

enter image description here

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,
              ),
            ),
          ],
        ),
      ),
    );
  }
}

5 个答案:

答案 0 :(得分:3)

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

1。仅缩放

如果您喜欢布局在某些参考屏幕尺寸上的外观,想要将文本区域视为一个框,并且只是在给定其他大小的屏幕的情况下向上或向下缩放整个框,则此解决方案有效。

参考参考屏幕。把所有东西按照预期排好。找出包含文本的框的大小(例如,通过在调试期间按't'显示渲染树)。然后用包含与测量尺寸相同的SizedBox的包装框包装。然后用FittedBox包装它。

限制基本上是在所有屏幕上以完全相同的方式布置文本,并且文本框的宽高比也相同。

2。多个参考

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

文本布局更流畅,包含框可以具有不同的宽高比,但您必须检查与您拥有的字体大小开关一样多的屏幕尺寸。虽然使用widget tests

可以很容易地确保文本不会在任何屏幕大小上溢出

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

答案 1 :(得分:3)

您可以使用自动文本包

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

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

答案 2 :(得分:1)

一个简单的嵌入式解决方案是将FittedBoxfit: 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'),
  )
)

答案 3 :(得分:0)

您是否尝试使用Flexible小部件

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

答案 4 :(得分:0)

这发生在我的应用中:

This is with a long title This is the long title in the horizontal mode

我通过计算一行中显示的最大字符数来解决,并在字符串长度较大时动态减少Text FontSize。

获取文字的字符宽度

首先,我计算了所显示的每个字符的宽度。 为此,我需要有效的容器宽度和显示的字符数。 为了获得屏幕宽度(实际上是容器宽度),我将我的文本小部件放在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值,然后我将它放在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),
    );
}

结果:

The text is dynamically reduced The long title in the horizontal mode has the same size

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

我想获得反馈。 :)