TextWidget を多用するアプリでは、属性の指定が面倒になりがちです。
こちらの記事では、
Material Design における Color System (Flutter での ColorScheme) と Custom Colors、
および TextStyle を活用することができていませんでした。
この記事は、それらに対応しつつ記述のしやすさを考慮したユーティリティクラスを紹介します。
省略したくなる、プレーンな記述
Flutter ColorScheme / CustomColors を活用するには、通常以下のようになります。
build(BuildContext context) {
return [
Text(
"Color: ColorScheme.primary",
style: TextStyle(
color: Theme.of(context).colorScheme.primary,
),
),
Text(
"Color: CustomColors.info",
style: TextStyle(
color: Theme.of(context).extension<CustomColors>()!.info,
),
),
];
}
さらに TextStyle からフォントのスケール等を指定したり、
Overflow Ellipsis などを併用すればこうなります。
build(BuildContext context) {
return [
Text(
"いろいろもりもり",
style: Theme.of(context).textTheme.labelLarge!.copyWith(
color: Theme.of(context).colorScheme.primary,
overflow: TextOverflow.ellipsis,
fontWeight: FontWeight.bold,
fontFamily: "NotoSansJP",
),
maxLines: 2,
),
];
}
特段書けないor読めないこともないですが、
私の製作しているアプリでは Text Widget は最も多用する Widget のひとつであったため、
読み書きの感覚を改善したいなと考えました。
ユーティリティを活用した省略結果
そこで、以下のようにシンプルに書けるようなユーティリティクラスを定義しました。
build(BuildContext context) {
return [
ThemedText(context)
.labelLarge
.primary
.overflowEllipsis
.bold
.notoSansJP
.maxLines(2)
.build("いろいろもりもり 改善後"),
];
}
ユーティリティクラス: ThemedText
私の環境ではこのようなメソッド群を定義していますが、
用途に合わせて整備するのがよいかと思います。
/// BuildContext に基づいたテーマを便利に取得して割り当て、Text Widget に割り当てて返すシンタックスシュガーよりのユーティリティ
///
/// - [TextTheme] の提供する各種 [TextStyle]
/// - [ColorScheme] の提供する各種 [Color]
/// - [CustomColor] の提供する各種 [Color]
///
/// (ex) ThemedText(context).displayLarge.success.build("Hello World!");
class ThemedText {
ThemedText(BuildContext context) : _context = context;
final BuildContext _context;
late final TextTheme _textTheme = Theme.of(_context).textTheme;
late final ColorScheme _colorScheme = Theme.of(_context).colorScheme;
late final CustomColors _customColors =
Theme.of(_context).extension<CustomColors>()!;
late TextStyle _textStyle = _textTheme.bodyMedium!;
String? _fontFamily;
double? _fontSize;
Color? _color;
FontWeight? _fontWeight;
int? _maxLines;
TextOverflow? _overflow;
TextHeightBehavior? _textHeightBehavior;
// Fonts
ThemedText _setFontFamily(String fontFamily) {
_fontFamily = fontFamily;
return this;
}
ThemedText get notoSansJP => _setFontFamily("NotoSansJP");
ThemedText get roboto => _setFontFamily("Roboto");
// TextStyles
ThemedText _setTextStyle(TextStyle? textStyle) {
if (textStyle == null) {
throw AppException.error("textStyle is null");
}
_textStyle = textStyle;
return this;
}
ThemedText get displayLarge => _setTextStyle(_textTheme.displayLarge);
ThemedText get displayMedium => _setTextStyle(_textTheme.displayMedium);
ThemedText get displaySmall => _setTextStyle(_textTheme.displaySmall);
ThemedText get headlineLarge => _setTextStyle(_textTheme.headlineLarge);
ThemedText get headlineMedium => _setTextStyle(_textTheme.headlineMedium);
ThemedText get headlineSmall => _setTextStyle(_textTheme.headlineSmall);
ThemedText get titleLarge => _setTextStyle(_textTheme.titleLarge);
ThemedText get titleMedium => _setTextStyle(_textTheme.titleMedium);
ThemedText get titleSmall => _setTextStyle(_textTheme.titleSmall);
ThemedText get bodyLarge => _setTextStyle(_textTheme.bodyLarge);
ThemedText get bodyMedium => _setTextStyle(_textTheme.bodyMedium);
ThemedText get bodySmall => _setTextStyle(_textTheme.bodySmall);
ThemedText get labelLarge => _setTextStyle(_textTheme.labelLarge);
ThemedText get labelMedium => _setTextStyle(_textTheme.labelMedium);
ThemedText get labelSmall => _setTextStyle(_textTheme.labelSmall);
// Colors
ThemedText _setColor(Color? color) {
if (color == null) {
throw AppException.error("color is null");
}
_color = color;
return this;
}
ThemedText get primary => _setColor(_colorScheme.primary);
ThemedText get onPrimary => _setColor(_colorScheme.onPrimary);
ThemedText get primaryContainer => _setColor(_colorScheme.primaryContainer);
ThemedText get onPrimaryContainer =>
_setColor(_colorScheme.onPrimaryContainer);
ThemedText get secondaryContainer =>
_setColor(_colorScheme.secondaryContainer);
ThemedText get onSecondaryContainer =>
_setColor(_colorScheme.onSecondaryContainer);
ThemedText get tertiary => _setColor(_colorScheme.tertiary);
ThemedText get onTertiary => _setColor(_colorScheme.onTertiary);
ThemedText get tertiaryContainer => _setColor(_colorScheme.tertiaryContainer);
ThemedText get onTertiaryContainer =>
_setColor(_colorScheme.onTertiaryContainer);
ThemedText get errorContainer => _setColor(_colorScheme.errorContainer);
ThemedText get onErrorContainer => _setColor(_colorScheme.onErrorContainer);
ThemedText get surfaceVariant => _setColor(_colorScheme.surfaceVariant);
ThemedText get onSurfaceVariant => _setColor(_colorScheme.onSurfaceVariant);
ThemedText get outline => _setColor(_colorScheme.outline);
ThemedText get outlineVariant => _setColor(_colorScheme.outlineVariant);
ThemedText get shadow => _setColor(_colorScheme.shadow);
ThemedText get scrim => _setColor(_colorScheme.scrim);
ThemedText get inverseSurface => _setColor(_colorScheme.inverseSurface);
ThemedText get onInverseSurface => _setColor(_colorScheme.onInverseSurface);
ThemedText get inversePrimary => _setColor(_colorScheme.inversePrimary);
ThemedText get surfaceTint => _setColor(_colorScheme.surfaceTint);
ThemedText get onSurface => _setColor(_colorScheme.onSurface);
ThemedText get error => _setColor(_colorScheme.error);
ThemedText get onError => _setColor(_colorScheme.onError);
// CustomColors
ThemedText get customSourceSuccess => _setColor(_customColors.sourceSuccess);
ThemedText get customSuccess => _setColor(_customColors.success);
ThemedText get customOnSuccess => _setColor(_customColors.onSuccess);
ThemedText get customSuccessContainer =>
_setColor(_customColors.successContainer);
ThemedText get customOnSuccessContainer =>
_setColor(_customColors.onSuccessContainer);
ThemedText get customSourceInfo => _setColor(_customColors.sourceInfo);
ThemedText get customInfo => _setColor(_customColors.info);
ThemedText get customOnInfo => _setColor(_customColors.onInfo);
ThemedText get customInfoContainer => _setColor(_customColors.infoContainer);
ThemedText get customOnInfoContainer =>
_setColor(_customColors.onInfoContainer);
// Other Custom
ThemedText fontSize(double fontSize) {
_fontSize = fontSize;
return this;
}
ThemedText fontWeight(FontWeight fontWeight) {
_fontWeight = fontWeight;
return this;
}
ThemedText get bold {
_fontWeight = FontWeight.bold;
return this;
}
ThemedText maxLines(int maxLines) {
_maxLines = maxLines;
return this;
}
ThemedText get overflowEllipsis {
_overflow = TextOverflow.ellipsis;
return this;
}
ThemedText textHeightBehavior(TextHeightBehavior textHeightBehavior) {
_textHeightBehavior = textHeightBehavior;
return this;
}
TextStyle get style => _textStyle.copyWith(
color: _color,
fontFamily: _fontFamily,
fontSize: _fontSize,
fontWeight: _fontWeight,
);
Text build(String text) {
return Text(
text,
maxLines: _maxLines,
overflow: _overflow,
textHeightBehavior: _textHeightBehavior,
style: style,
);
}
}