如何在Flutter中动态调整文本大小?

时间:2018-06-07 22:58:46

标签: flutter

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

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

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

    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&#34,我如何确定文字占据的高度? 也许我以错误的方式接近这个并且我应该使用maxLines来确定这一点?但是,我们怎么知道我们已达到maxLines以上?

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

9 个答案:

答案 0 :(得分:18)

使用 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),
                          ),)

答案 1 :(得分:8)

您可以使用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

答案 2 :(得分:5)

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),
              ),
            ),
          ),

答案 3 :(得分:3)

根据您的使用情况,以下是我尝试过的可能适合您的事项列表:https://github.com/flutter/flutter/issues/18431

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

答案 4 :(得分:3)

Responsive_Flutter ,自阅读您的问题以来,我遇到了同样的问题。我发现它每次都能使用,可以使用此包来调整字体大小。

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

https://github.com/layounisl/responsive_flutter

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

  1. 将依赖项添加到yaml文件“ response_flutter:^ 0.0.4”
  2. 导入'package:sensitive_flutter / sensitive_flutter.dart';
  3. child:Text(“响应式颤动”, 样式:TextStyle(fontSize:ResponsiveFlutter.of(context).fontSize(3)),

App using Flutter

答案 5 :(得分:2)

您可以使用FittedBox来根据高度或宽度来管理文本。

例如。

只需将Text小部件包装到FittedBox小部件中即可,在这里我想根据宽度调整AppBar文本的大小。

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

文本将根据AppBar的宽度进行调整。

答案 6 :(得分:0)

只需根据文本长度和最大渲染面积生成字体大小。 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

答案 7 :(得分:0)

我发现最简单的方法是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,
            ),
          ),
        ),
      ),
    );
  }
}

答案 8 :(得分:-2)

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