弃用 textScaleFactor,转而使用 TextScaler
概述
#为采用 Android 14 非线性字体缩放功能 做准备,Flutter 框架中所有 textScaleFactor
的出现都已被弃用并由 TextScaler
取代。
背景
#许多平台允许用户在系统偏好设置中全局缩放文本内容。过去,缩放策略被捕获为名为 textScaleFactor
的单个 double
值,因为文本缩放是成比例的:scaledFontSize = textScaleFactor x unScaledFontSize
。例如,当 textScaleFactor
为 2.0 且开发者指定的字体大小为 14.0 时,实际字体大小为 2.0 x 14.0 = 28.0。
随着 Android 14 非线性字体缩放 的引入,为了防止已经很大的文本被过度缩放,较大的文本相较于较小的文本以更小的比例缩放。用于“比例”缩放的 textScaleFactor
标量值不足以表示这种新的缩放策略。用 TextScaler
替换 textScaleFactor
拉取请求引入了一个新类 TextScaler
来取代 textScaleFactor
,以为此新功能做准备。非线性文本缩放将在另一个拉取请求中引入。
变更说明
#引入了一个新接口 TextScaler
,它代表一种文本缩放策略。
abstract class TextScaler {
double scale(double fontSize);
double get textScaleFactor; // Deprecated.
}
使用 scale
方法来缩放字体大小,而不是 textScaleFactor
。textScaleFactor
获取器提供一个估算的 textScaleFactor
值,它用于向后兼容,并且已被标记为弃用,将在 Flutter 的未来版本中移除。
新类已在以下 API 中取代 double textScaleFactor
(double textScaleFactor
-> TextScaler textScaler
)
绘图库
#受影响的 API | 错误消息 |
---|---|
InlineSpan.build({ double textScaleFactor = 1.0 }) 参数 | 命名参数“textScaleFactor”未定义。 |
TextStyle.getParagraphStyle({ double TextScaleFactor = 1.0 }) 参数 | 命名参数“textScaleFactor”未定义。 |
TextStyle.getTextStyle({ double TextScaleFactor = 1.0 }) 参数 | “textScaleFactor”已弃用,不应使用。 |
TextPainter({ double TextScaleFactor = 1.0 }) 构造函数参数 | “textScaleFactor”已弃用,不应使用。 |
TextPainter.textScaleFactor 获取器和设置器 | “textScaleFactor”已弃用,不应使用。 |
TextPainter.computeWidth({ double TextScaleFactor = 1.0 }) 参数 | “textScaleFactor”已弃用,不应使用。 |
TextPainter.computeMaxIntrinsicWidth({ double TextScaleFactor = 1.0 }) 参数 | “textScaleFactor”已弃用,不应使用。 |
渲染库
#受影响的 API | 错误消息 |
---|---|
RenderEditable({ double TextScaleFactor = 1.0 }) 构造函数参数 | “textScaleFactor”已弃用,不应使用。 |
RenderEditable.textScaleFactor 获取器和设置器 | “textScaleFactor”已弃用,不应使用。 |
RenderParagraph({ double TextScaleFactor = 1.0 }) 构造函数参数 | “textScaleFactor”已弃用,不应使用。 |
RenderParagraph.textScaleFactor 获取器和设置器 | “textScaleFactor”已弃用,不应使用。 |
小部件库
#受影响的 API | 错误消息 |
---|---|
MediaQueryData({ double TextScaleFactor = 1.0 }) 构造函数参数 | “textScaleFactor”已弃用,不应使用。 |
MediaQueryData.textScaleFactor 获取器 | “textScaleFactor”已弃用,不应使用。 |
MediaQueryData.copyWith({ double? TextScaleFactor }) 参数 | “textScaleFactor”已弃用,不应使用。 |
MediaQuery.maybeTextScaleFactorOf(BuildContext context) 静态方法 | “maybeTextScaleFactorOf”已弃用,不应使用。 |
MediaQuery.textScaleFactorOf(BuildContext context) 静态方法 | “textScaleFactorOf”已弃用,不应使用。 |
RichText({ double TextScaleFactor = 1.0 }) 构造函数参数 | “textScaleFactor”已弃用,不应使用。 |
RichText.textScaleFactor 获取器 | “textScaleFactor”已弃用,不应使用。 |
Text({ double? TextScaleFactor = 1.0 }) 构造函数参数 | “textScaleFactor”已弃用,不应使用。 |
Text.rich({ double? TextScaleFactor = 1.0 }) 构造函数参数 | “textScaleFactor”已弃用,不应使用。 |
Text.textScaleFactor 获取器 | “textScaleFactor”已弃用,不应使用。 |
EditableText({ double? TextScaleFactor = 1.0 }) 构造函数参数 | “textScaleFactor”已弃用,不应使用。 |
EditableText.textScaleFactor 获取器 | “textScaleFactor”已弃用,不应使用。 |
Material 库
#受影响的 API | 错误消息 |
---|---|
SelectableText({ double? TextScaleFactor = 1.0 }) 构造函数参数 | “textScaleFactor”已弃用,不应使用。 |
SelectableText.rich({ double? TextScaleFactor = 1.0 }) 构造函数参数 | “textScaleFactor”已弃用,不应使用。 |
SelectableText.textScaleFactor 获取器 | “textScaleFactor”已弃用,不应使用。 |
迁移指南
#Flutter 框架提供的小部件已完成迁移。仅当您使用前面表格中列出的任何弃用符号时,才需要进行迁移。
迁移暴露 textScaleFactor
的 API
#之前
abstract class _MyCustomPaintDelegate {
void paint(PaintingContext context, Offset offset, double textScaleFactor) {
}
}
之后
abstract class _MyCustomPaintDelegate {
void paint(PaintingContext context, Offset offset, TextScaler textScaler) {
}
}
迁移使用 textScaleFactor
的代码
#如果您当前没有直接使用 textScaleFactor
,而是将其传递给接收 textScaleFactor
的另一个 API,并且接收方 API 已经迁移,那么这相对简单
之前
RichText(
textScaleFactor: MediaQuery.textScaleFactorOf(context),
...
)
之后
RichText(
textScaler: MediaQuery.textScalerOf(context),
...
)
如果提供 textScaleFactor
的 API 尚未迁移,请考虑等待已迁移的版本。
如果您希望自行计算缩放后的字体大小,请使用 TextScaler.scale
而不是 *
二元运算符
之前
final scaledFontSize = textStyle.fontSize * MediaQuery.textScaleFactorOf(context);
之后
final scaledFontSize = MediaQuery.textScalerOf(context).scale(textStyle.fontSize);
如果您使用 textScaleFactor
来缩放非字体大小的尺寸,则没有将代码迁移到非线性缩放的通用规则,并且可能需要以不同的方式实现 UI。沿用 MyTooltipBox
示例
MyTooltipBox(
size: chatBoxSize * textScaleFactor,
child: RichText(..., style: TextStyle(fontSize: 20)),
)
您可以选择通过将 TextScaler
应用于字体大小 20 来使用“有效”文本缩放因子:chatBoxSize * textScaler.scale(20) / 20
,或者重新设计 UI 并让小部件采用其自身的固有大小。
覆盖小部件子树中的文本缩放策略
#要覆盖小部件子树中使用的现有 TextScaler
,请按如下方式覆盖 MediaQuery
之前
MediaQuery(
data: MediaQuery.of(context).copyWith(textScaleFactor: 2.0),
child: child,
)
之后
MediaQuery(
data: MediaQuery.of(context).copyWith(textScaler: _myCustomTextScaler),
child: child,
)
然而,很少需要创建自定义的 TextScaler
子类。MediaQuery.withNoTextScaling
(它创建一个小部件,完全禁用其子树的文本缩放)和 MediaQuery.withClampedTextScaling
(它创建一个小部件,将缩放后的字体大小限制在 [minScaleFactor * fontSize, maxScaleFactor * fontSize]
范围内)是涵盖需要覆盖文本缩放策略的常见情况的便捷方法。
示例
#禁用图标字体的文本缩放
之前
MediaQuery(
data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0),
child: IconTheme(
data: ..,
child: icon,
),
)
之后
MediaQuery.withNoTextScaling(
child: IconTheme(
data: ...
child: icon,
),
)
防止内容过度缩放
之前
final mediaQueryData = MediaQuery.of(context);
MediaQuery(
data: mediaQueryData.copyWith(textScaleFactor: math.min(mediaQueryData.textScaleFactor, _kMaxTitleTextScaleFactor),
child: child,
)
之后
MediaQuery.withClampedTextScaling(
maxScaleFactor: _kMaxTitleTextScaleFactor,
child: title,
)
禁用非线性文本缩放
如果您想在应用程序完全迁移之前,在 Android 14 上暂时选择退出非线性文本缩放,请将修改后的 MediaQuery
放在应用程序小部件树的顶部
runApp(
Builder(builder: (context) {
final mediaQueryData = MediaQuery.of(context);
final mediaQueryDataWithLinearTextScaling = mediaQueryData
.copyWith(textScaler: TextScaler.linear(mediaQueryData.textScaler.textScaleFactor));
return MediaQuery(data: mediaQueryDataWithLinearTextScaling, child: realWidgetTree);
}),
);
此方法使用了弃用的 textScaleFactor
API,一旦从 Flutter API 中移除,它将停止工作。
时间线
#落地版本:3.13.0-4.0.pre
稳定版本:3.16
参考资料
#API 文档
TextScaler
MediaQuery.textScalerOf
MediaQuery.maybeTextScalerOf
MediaQuery.withNoTextScaling
MediaQuery.withClampedTextScaling
相关问题
相关 PR