Saltar al contenido principal

Depreciar textScaleFactor en favor de TextScaler

La nueva clase, TextScaler, reemplaza el escalar textScaleFactor en preparación para el soporte de escalado de texto no lineal en Android 14.

Resumen

#

En preparación para adoptar la función de escalado de fuente no lineal de Android 14 , todas las apariciones de textScaleFactor en el framework de Flutter han quedado obsoletas y se han reemplazado por TextScaler.

Contexto

#

Muchas plataformas permiten a los usuarios escalar el contenido textual hacia arriba o hacia abajo de forma global en las preferencias del sistema. En el pasado, la estrategia de escalado se capturaba como un único valor double llamado textScaleFactor, ya que el escalado de texto era proporcional: scaledFontSize = textScaleFactor x unScaledFontSize. Por ejemplo, cuando textScaleFactor es 2.0 y el tamaño de fuente especificado por el desarrollador es 14.0, el tamaño de fuente real es 2.0 x 14.0 = 28.0.

Con la introducción del escalado de fuente no lineal de Android 14, el texto más grande se escala a un ritmo menor en comparación con el texto más pequeño, para evitar el escalado excesivo del texto que ya es grande. El valor escalar textScaleFactor utilizado por el escalado "proporcional" no es suficiente para representar esta nueva estrategia de escalado. La solicitud de extracción Replaces textScaleFactor with TextScaler introdujo una nueva clase TextScaler para reemplazar textScaleFactor en preparación para esta nueva característica. El escalado de texto no lineal se introduce en una solicitud de extracción diferente.

Descripción del cambio

#

Presentando una nueva interfaz TextScaler, la cual representa una estrategia de escalado de texto.

dart
abstract class TextScaler {
  double scale(double fontSize);
  double get textScaleFactor; // Deprecated.
}

Usa el método scale para escalar los tamaños de fuente en lugar de textScaleFactor. El getter textScaleFactor proporciona un valor estimado de textScaleFactor, es para propósitos de compatibilidad con versiones anteriores y ya está marcado como depreciado, y será eliminado en una versión futura de Flutter.

La nueva clase ha reemplazado a double textScaleFactor (double textScaleFactor -> TextScaler textScaler), en las siguientes APIs:

Biblioteca de pintura

#
APIs afectadasMensaje de error
Argumento de InlineSpan.build({ double textScaleFactor = 1.0 }) El parámetro con nombre 'textScaleFactor' no está definido.
Argumento de TextStyle.getParagraphStyle({ double TextScaleFactor = 1.0 }) El parámetro con nombre 'textScaleFactor' no está definido.
Argumento de TextStyle.getTextStyle({ double TextScaleFactor = 1.0 }) 'textScaleFactor' está depreciado y no debería ser usado.
Argumento del constructor de TextPainter({ double TextScaleFactor = 1.0 }) 'textScaleFactor' está depreciado y no debería ser usado.
Getter y setter de TextPainter.textScaleFactor 'textScaleFactor' está depreciado y no debería ser usado.
Argumento de TextPainter.computeWidth({ double TextScaleFactor = 1.0 }) 'textScaleFactor' está depreciado y no debería ser usado.
Argumento de TextPainter.computeMaxIntrinsicWidth({ double TextScaleFactor = 1.0 }) 'textScaleFactor' está depreciado y no debería ser usado.

Biblioteca de renderizado

#
APIs afectadasMensaje de error
Argumento del constructor de RenderEditable({ double TextScaleFactor = 1.0 }) 'textScaleFactor' está depreciado y no debería ser usado.
Getter y setter de RenderEditable.textScaleFactor 'textScaleFactor' está depreciado y no debería ser usado.
Argumento del constructor de RenderParagraph({ double TextScaleFactor = 1.0 }) 'textScaleFactor' está depreciado y no debería ser usado.
Getter y setter de RenderParagraph.textScaleFactor 'textScaleFactor' está depreciado y no debería ser usado.

Biblioteca de Widgets

#
APIs afectadasMensaje de error
Argumento del constructor de MediaQueryData({ double TextScaleFactor = 1.0 }) 'textScaleFactor' está depreciado y no debería ser usado.
Getter de MediaQueryData.textScaleFactor 'textScaleFactor' está depreciado y no debería ser usado.
Argumento de MediaQueryData.copyWith({ double? TextScaleFactor }) 'textScaleFactor' está depreciado y no debería ser usado.
Método estático MediaQuery.maybeTextScaleFactorOf(BuildContext context) 'maybeTextScaleFactorOf' está depreciado y no debería ser usado.
Método estático MediaQuery.textScaleFactorOf(BuildContext context) 'textScaleFactorOf' está depreciado y no debería ser usado.
Argumento del constructor de RichText({ double TextScaleFactor = 1.0 }) 'textScaleFactor' está depreciado y no debería ser usado.
Getter de RichText.textScaleFactor 'textScaleFactor' está depreciado y no debería ser usado.
Argumento del constructor de Text({ double? TextScaleFactor = 1.0 }) 'textScaleFactor' está depreciado y no debería ser usado.
Argumento del constructor de Text.rich({ double? TextScaleFactor = 1.0 }) 'textScaleFactor' está depreciado y no debería ser usado.
Getter de Text.textScaleFactor 'textScaleFactor' está depreciado y no debería ser usado.
Argumento del constructor de EditableText({ double? TextScaleFactor = 1.0 }) 'textScaleFactor' está depreciado y no debería ser usado.
Getter de EditableText.textScaleFactor 'textScaleFactor' está depreciado y no debería ser usado.

Biblioteca Material

#
APIs afectadasMensaje de error
Argumento del constructor de SelectableText({ double? TextScaleFactor = 1.0 }) 'textScaleFactor' está depreciado y no debería ser usado.
Argumento del constructor de SelectableText.rich({ double? TextScaleFactor = 1.0 }) 'textScaleFactor' está depreciado y no debería ser usado.
Getter de SelectableText.textScaleFactor 'textScaleFactor' está depreciado y no debería ser usado.

Guía de migración

#

Los widgets proporcionados por el framework de Flutter ya están migrados. La migración es necesaria solo si estás usando alguno de los símbolos depreciados listados en las tablas anteriores.

Migrar tus APIs que exponen textScaleFactor

#

Antes:

dart
abstract class _MyCustomPaintDelegate {
  void paint(PaintingContext context, Offset offset, double textScaleFactor) {
  }
}

Después:

dart
abstract class _MyCustomPaintDelegate {
  void paint(PaintingContext context, Offset offset, TextScaler textScaler) {
  }
}

Migrar el código que consume textScaleFactor

#

Si actualmente no estás usando textScaleFactor directamente, sino que lo estás pasando a una API diferente que recibe un textScaleFactor, y la API receptora ya ha sido migrada, entonces es relativamente sencillo:

Antes:

dart
RichText(
  textScaleFactor: MediaQuery.textScaleFactorOf(context),
  ...
)

Después:

dart
RichText(
  textScaler: MediaQuery.textScalerOf(context),
  ...
)

Si la API que proporciona textScaleFactor no ha sido migrada, considera esperar a la versión migrada.

Si deseas calcular el tamaño de fuente escalado tú mismo, usa TextScaler.scale en lugar del operador binario *:

Antes:

dart
final scaledFontSize = textStyle.fontSize * MediaQuery.textScaleFactorOf(context);

Después:

dart
final scaledFontSize = MediaQuery.textScalerOf(context).scale(textStyle.fontSize);

Si estás usando textScaleFactor para escalar dimensiones que no son tamaños de fuente, no existen reglas genéricas para migrar el código al escalado no lineal, y podría requerir que la interfaz de usuario se implemente de manera diferente. Reutilizando el ejemplo MyTooltipBox:

dart
MyTooltipBox(
  size: chatBoxSize * textScaleFactor,
  child: RichText(..., style: TextStyle(fontSize: 20)),
)

Podrías elegir usar el factor de escala de texto "efectivo" aplicando el TextScaler sobre el tamaño de fuente 20: chatBoxSize * textScaler.scale(20) / 20, o rediseñar la interfaz de usuario y dejar que el widget asuma su propio tamaño intrínseco.

Anular la estrategia de escalado de texto en un subárbol de widgets

#

Para anular el TextScaler existente usado en un subárbol de widgets, anula el MediaQuery de esta manera:

Antes:

dart
MediaQuery(
  data: MediaQuery.of(context).copyWith(textScaleFactor: 2.0),
  child: child,
)

Después:

dart
MediaQuery(
  data: MediaQuery.of(context).copyWith(textScaler: _myCustomTextScaler),
  child: child,
)

Sin embargo, rara vez es necesario crear una subclase personalizada de TextScaler. MediaQuery.withNoTextScaling (que crea un widget que deshabilita el escalado de texto por completo para su subárbol secundario) y MediaQuery.withClampedTextScaling (que crea un widget que restringe el tamaño de fuente escalado dentro del rango [minScaleFactor * fontSize, maxScaleFactor * fontSize]), son métodos de conveniencia que cubren casos comunes en los que la estrategia de escalado de texto necesita ser anulada.

Ejemplos

#

Deshabilitar el escalado de texto para fuentes de iconos

Antes:

dart
MediaQuery(
  data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0),
  child: IconTheme(
    data: ..,
    child: icon,
  ),
)

Después:

dart
MediaQuery.withNoTextScaling(
  child: IconTheme(
    data: ...
    child: icon,
  ),
)

Preventing Contents From Overscaling

Antes:

dart
final mediaQueryData = MediaQuery.of(context);
MediaQuery(
  data: mediaQueryData.copyWith(textScaleFactor: math.min(mediaQueryData.textScaleFactor, _kMaxTitleTextScaleFactor),
  child: child,
)

Después:

dart
MediaQuery.withClampedTextScaling(
  maxScaleFactor: _kMaxTitleTextScaleFactor,
  child: title,
)

Disabling Nonlinear Text Scaling

Si deseas excluirte temporalmente del escalado de texto no lineal en Android 14 hasta que tu aplicación esté completamente migrada, coloca un MediaQuery modificado en la parte superior del árbol de widgets de tu aplicación:

dart
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);
  }),
);

Este truco utiliza la API depreciada textScaleFactor y dejará de funcionar una vez que sea eliminada de la API de Flutter.

Timeline

#

Llegó en la versión: 3.13.0-4.0.pre
En la versión estable: 3.16

Referencias

#

Documentación de la API:

Issues relevantes:

PRs relevantes: