在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处理文本缩放的资料请关注脚本之家其它相关文章!