如何在flutter中使文本达到宽度允许的大小

问题描述 投票:0回答:8

我有一个容器,需要在其中显示条形码,并且我希望条形码在屏幕上尽可能宽。 现在我将字体大小设置为适合所有设备的合理大小,但这当然只是暂时的。 我该如何解决这个问题?这是我用于构建小部件的代码。

@override
Widget build(BuildContext context) {
  return Scaffold(
      appBar: AppBar(
      title: Text(_title),
    ),
    body: Container(
    padding: const EdgeInsets.all(12.0),
    child: Column(
      children: <Widget>[ 
        SizedBox(
          width: double.infinity,
          child: Text(_barcode, style: TextStyle(fontFamily: 'Code128', fontSize: 90.0))
        ),
        Text(_barcode, style: TextStyle(fontSize: 40.0))
        ]
      ),
    )
  );
}
flutter flutter-layout
8个回答
62
投票

我相信您正在寻找的是

FittedBox

BoxFit 应用您想要拉伸/缩放子项以适合框的任何“适合”。它不会对文本执行纯粹的“拉伸”,而是对其应占用的空间进行执行。您不应同时指定文本的大小。

看起来像这样:

import 'package:flutter/material.dart';

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

class MyApp extends StatefulWidget {
  @override
  MyAppState createState() {
    return new MyAppState();
  }
}

class MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: SafeArea(
          child: Center(
            child: Container(
              color: Colors.blue,
              width: 300.0,
              height: 200.0,
              child: FittedBox(
                fit: BoxFit.contain,
                child: Text("Whee"),
              ),
            ),
          ),
        ),
      ),
    );
  }
}

如果您想实际“拉伸”文本(即使实际字符更宽或更高),您必须做一些更自定义的事情。

如果是这种情况,请查看 CustomPaintCustomPainterTextPainterCanvas translatescale 选项。基本上,您需要创建一个扩展 CustomPainter 的类,在其中创建一个 TextPainter,将其布局为特定大小,将其绘制到画布上,然后缩放它以适合 CustomPainter 的实际大小(或者您是否缩放首先画布 - 我忘记了......)。然后您将该类的实例传递给 CustomPaint。


13
投票

FittedBox 对我有用,但有一个转折点。我还必须将 fontSize 设置为一个大数字才能正常工作。希望这有帮助。

child: FittedBox(
                  fit: BoxFit.fitHeight,
                  child: Text(
                    "Your Expanded Text :)",
                    style: TextStyle(fontSize: 400.0),
                  ),
                ),

10
投票

问题中的代码示例有一个

Text
小部件作为
children:
小部件的
Column
之一。
Text
父级的宽度未知。

因此,在这种情况下,要最大化

Text
小部件的宽度和大小,请将
Text
小部件包裹在
FittedBox
中,然后包裹在
Expanded
中。

child: Column(children: <Widget>[
  Expanded(
    child: FittedBox(
        fit: BoxFit.contain,
        child: Text(
          '123',
        )),
  ),
]),

即使设备旋转或屏幕调整大小,

Text
尺寸也应该自动正确调整大小,而不会出现溢出问题。

扩展:

/// A widget that expands a child of a [Row], [Column], or [Flex]
/// so that the child fills the available space.
///
/// Using an [Expanded] widget makes a child of a [Row], [Column], or [Flex]
/// expand to fill the available space along the main axis (e.g., horizontally for
/// a [Row] or vertically for a [Column]). If multiple children are expanded,
/// the available space is divided among them according to the [flex] factor.

来自

/flutter/packages/flutter/lib/src/widgets/basic.dart

固定盒:

/// Creates a widget that scales and positions its child within itself according to [fit].


3
投票

您可以使用安装盒小部件。

FittedBox(child:Text('text sample'));

https://api.flutter.dev/flutter/widgets/FittedBox-class.html


3
投票

FittedBox
仅在提供一些约束时才起作用,因此请确保提供一个约束,例如提供高度,如下所示:

SizedBox(
  height: 400, // 1st set height
  child: FittedBox(child: Text("*")), // 2nd wrap in FittedBox
)

2
投票

使用

TextPainter.width
和 for 循环找到最大的合适字体大小(添加 +1 不是很有效,您可能需要对其进行微调):

import 'package:flutter/material.dart';

main() => runApp(MaterialApp(
      home: MyHomePage(),
      theme: ThemeData(platform: TargetPlatform.iOS),
    ));

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Text autoscale'),
      ),
      body: Padding(
        padding: EdgeInsets.all(32.0),
        child: Center(
          child: LayoutBuilder(
            builder: (BuildContext context, BoxConstraints constraints) {
              final text = 'Hello World';
              final style = TextStyle(fontWeight: FontWeight.bold); // apply your barcode font here
              final fontSize = calculateAutoscaleFontSize(text, style, 30.0, constraints.maxWidth);
              return Text(
                text,
                style: style.copyWith(fontSize: fontSize),
                maxLines: 1,
              );
            },
          ),
        ),
      ),
    );
  }
}

double calculateAutoscaleFontSize(String text, TextStyle style, double startFontSize, double maxWidth) {
  final textPainter = TextPainter(textDirection: TextDirection.ltr);

  var currentFontSize = startFontSize;

  for (var i = 0; i < 100; i++) {
    // limit max iterations to 100
    final nextFontSize = currentFontSize + 1;
    final nextTextStyle = style.copyWith(fontSize: nextFontSize);
    textPainter.text = TextSpan(text: text, style: nextTextStyle);
    textPainter.layout();
    if (textPainter.width >= maxWidth) {
      break;
    } else {
      currentFontSize = nextFontSize;
      // continue iteration
    }
  }

  return currentFontSize;
}

2
投票

将文本包裹在 FittedBox 小部件中,以强制文本被框包围。 FittedBox 的大小将取决于它的父级小部件。在 FittedBox 中,文本小部件可以简单地“覆盖”该框,因此文本不会拉伸以填充 FittedBox 中的可用空间。枚举 BoxFit.fill 是一种拉伸文本以适合 FittedBox 内整个可用空间的方法。您可以通过更改 FittedBox 的父级 Container 的高度和宽度来更改盒子的尺寸。

Container(
  height: _height,
  width: _width,
  FittedBox(               
    fit: BoxFit.fill,
    child: Text("Whee"),
  )
)

0
投票

我已经更改了boformers的答案,以便现在使用孔隙度因子来计算最大字体大小。这种方法节省了大量的计算时间,因为不再存在循环;现在,每个字体大小都是同时计算的。 此外,还考虑了最大高度。此外,现在有一个设置最大字体大小的选项,例如,如果您想要多个具有相同字体大小的文本小部件,这会很有用。

double calculateAutoscaleFontSize(String text, TextStyle style,
    double maxFontSize, double maxWidth, double maxHeight) {
  double calcWidth(
      double fontSize, TextPainter textPainter, String text, TextStyle style) {
    final nextTextStyle = style.copyWith(fontSize: fontSize);
    textPainter.text = TextSpan(text: text, style: nextTextStyle);
    textPainter.layout();
    return textPainter.width;
  }

  final textPainter = TextPainter(textDirection: TextDirection.ltr);
  final double width10 = calcWidth(10, textPainter, text, style);
  final double height10 = textPainter.height;
  final double width110 = calcWidth(110, textPainter, text, style);
  final double height110 = textPainter.height;

  final double withPerFontSize = (width110 - width10) / 100;
  final double heightPerFontSize = (height110 - height10) / 100;

  final double maxWidthFontSize = maxWidth / withPerFontSize;
  final double maxHeightFontSize = maxHeight / heightPerFontSize;
  final double maxCalculatedFontSize = maxWidthFontSize < maxHeightFontSize
      ? maxWidthFontSize
      : maxHeightFontSize;

  return maxCalculatedFontSize < maxFontSize
      ? maxCalculatedFontSize
      : maxFontSize;
}

我已经对此进行了测试,如果对结果进行四舍五入,它会输出与 boformers 答案相同的字体大小。 我无法测试很多字体,但根据this答案,字体大小是字母应具有的最大高度的近似值。在这种情况下,每个字母的宽度按比例取决于此最大高度,这意味着它也按比例取决于字体大小。虽然这个因素对于每种情况下的每个字母都不同,但在我的方法中,字母不会改变,因此整个文本段落的因素保持不变,这意味着我的方法应该适用于每种字体。

© www.soinside.com 2019 - 2024. All rights reserved.