Android

关注公众号 jb51net

关闭
首页 > 软件编程 > Android > Flutter处理文本缩放

在Flutter中正确处理文本缩放的解决方案

作者:独立开发者张张

这篇文章主要介绍了在Flutter中正确处理文本缩放的解决方案,本教程的结构首先介绍最简单且最有影响力的解决方案,后面的部分涵盖了较难实施且总体影响较小的解决方案,但它们对于解决特定情况很有用,需要的朋友可以参考下

本教程的结构首先介绍最简单且最有影响力的解决方案。后面的部分涵盖了较难实施且总体影响较小的解决方案,但它们对于解决特定情况很有用。

限制文本缩放的可能范围

您可以为 MaterialApp 设置最小和最大缩放系数,这将确保所有文本在指定范围内缩放。更小的界限需要更少的努力来保持可读性和美观性。不过,边界的选择应取决于目标受众。例如,如果您的应用程序是为老年用户设计的,您应该考虑使用较宽松的边界来满足他们的需求。

MaterialApp(
  ...
  builder: (_, child) => MediaQuery(
    data: MediaQuery.of(context).copyWith(
      textScaler: MediaQuery.of(context)
          .textScaler
          .clamp(minScaleFactor: 0.8, maxScaleFactor: 1.6),
    ),
    child: child!,
  ),
);

不要对包含文本的元素使用固定高度

看一下这段代码:

//不要这样做
SizedBox(
  height: 100,
  child: Card(
    child: Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Text("Title", style: TextStyle(fontSize: 30), maxLines: 1),
          Text("Subtitle", maxLines: 1),
        ],
      ),
    ),
  ),
),

可能会出现什么问题?

正如您可能已经猜到的,增加文本大小可能会导致 SizedBox 的内容占用过多空间。

更好的解决方案是根据内容高度和填充来设置项目的高度。此外,您可以使用 ConstrainedBox 设置最小高度。

ConstrainedBox(
  constraints: const BoxConstraints(minHeight: 100),
  child: const Card(
    child: Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Text("Title", style: TextStyle(fontSize: 30), maxLines: 1),
          Text("Subtitle", maxLines: 1),
        ],
      ),
    ),
  ),
),

因此,在 100% 比例下,我们得到了一个相同的布局,而在 160% 比例下,我们得到了一个有效的布局。

这同样适用于 ListView,如果您使用 itemExtent,请考虑使用字体比例计算或提供一个 prototypeItem

让我们继续,想象一下这样的布局:

项目 A 来自上一个示例。项目 B 有一些填充,应该也能处理增加的文本缩放。屏幕底部有足够的空间。那么,可能会出什么问题呢?

不要忘记屏幕较小的手机。此外,当语言发生变化时,文本长度也会发生变化。

确保内容可滚动

首先,我们应该消除任何溢出,以确保我们的用户可以访问所有内容。添加一个简单的 SingleChildScrollView 将解决这个问题。

考虑对边距和填充使用自适应值

这可能是一个有争议的方法,但想象一下您自己是一个需要使用更大字体的用户。您希望看到大量未使用的空间还是清楚地阅读文本?

让我们使用取决于逻辑像素数的值来显示文本。您可以将 smallScreenThreshold 调整为任何对您的应用程序最合理的值。

class Dimens {
  static const smallScreenThreshold = 300;
  static bool isSmallWidth(BuildContext context) {
    return MediaQuery.of(context).size.width /
            MediaQuery.textScalerOf(context).scale(1) <
        smallScreenThreshold;
  }

  static double small(BuildContext context) => isSmallWidth(context) ? 4 : 8;
  static double medium(BuildContext context) => isSmallWidth(context) ? 8 : 16;
  static double large(BuildContext context) => isSmallWidth(context) ? 16 : 32;
}

请注意,如果您想遵循人机界面指南和 Material Design,这些值应能被 4 整除。

基于这些 Dimens 我们可以为插图创建一个类:

class Insets {
  static EdgeInsets small(BuildContext context) =>
      EdgeInsets.all(Dimens.small(context));
      
  static EdgeInsets medium(BuildContext context) =>
      EdgeInsets.all(Dimens.medium(context));

  static EdgeInsets large(BuildContext context) =>
      EdgeInsets.all(Dimens.large(context));
}

在代码中我们将其替换为:

//padding: const EdgeInsets.all(16),
padding: Insets.medium(context),

//SizedBox(height: 16),
SizedBox(height: Dimens.medium(context)),

结果,我们赢得了更多的空间来在屏幕上绘制文本:

限制标题文字大小的扩展范围

增加字体比例的主要目的是使视力下降的人能够阅读内容。但是,应用程序的某些部分(例如标题)由于字体较大,可能已经可以访问。为了解决这个问题,我们可以限制文本可以放大的程度。实现此目的的一种方法是为标题创建自定义小部件:

class TitleText extends StatelessWidget {
  final String text;
  final TextStyle style;

  const TitleText(this.text, {required this.style, super.key});

  static const double maxRealFontSize = 30;

  @override
  Widget build(BuildContext context) {
    if (MediaQuery.textScalerOf(context).scale(style.fontSize!) >
        maxRealFontSize) {
      return Text(
        text,
        style: style.copyWith(
          fontSize: maxRealFontSize / MediaQuery.textScalerOf(context).scale(1),
        ),
      );
    }
    return Text(text, style: style);
  }
}

通过这样做,我们可以在不失去可读性的情况下赢得更多空间。您可以将该 maxRealFontSize 更改为更适合您的应用的任何值。

指定最大行数和文本溢出

不要忘记,某些文本在正常文本比例的大屏幕上可能看起来不错,但在某些其他条件下可能会占用更多的垂直空间,但您并不总是需要显示其完整内容,例如字幕。只需将 maxLines 值添加到文本小部件即可。

使用字符串的替代版本

但并不总是能够以仍然包含有用信息的方式缩短字符串。此外,不同语言的词序也不同。英语中的第一个单词可能位于另一种语言的句子末尾。让我们考虑这个国际化 (i18n) 字符串的示例:

"tasksDone": {
    "one": "You have done $completed of $n tasks",
    "other": "You have done $completed of $n tasks"
},
"tasksDoneShort": {
    "one": "$completed/$n tasks done",
    "other": "$completed/$n tasks done"
},

最有意义的部分是显示数字的部分。在较短的版本中,我们把它放在开头,使整个字符串更短。在代码中,你可以这样使用它:

Text(
  Dimens.isSmallWidth(context)
      ? t.tasksDoneShort(n: 10, completed: 5)
      : t.tasksDone(n: 10, completed: 5),
   maxLines: 1,
)

正如您在屏幕截图中看到的,缩短的版本有助于显示所需的信息。

以上就是在Flutter中正确处理文本缩放的解决方案的详细内容,更多关于Flutter处理文本缩放的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文