组件
已经封装好的组件,可以直接替代原有 Text
组件使用,这里也添加了一些便捷的样式用于 ListTile
中的使用。
其中的 Marquee 组件来自于 pub 中的插件,当然也可以去看看是怎么实现的,这里就不展开讲了,实现原理也比较简单,通过 ListView 等可滚动组件来模拟 Marquee 效果
class AdaptiveText extends StatelessWidget {
final String text;
final TextStyle? style;
final double? maxWidth;
final bool? isTileTitle;
final bool? isTileSubtitle;
final bool? isPrimaryTitle;
final bool? isTitle;
const AdaptiveText(
this.text, {
super.key,
this.style,
this.maxWidth,
this.isTileTitle,
this.isTileSubtitle,
this.isPrimaryTitle,
this.isTitle,
});
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final textTheme = Theme.of(context).textTheme;
final textScaler = MediaQuery.textScalerOf(context);
var textStyle = style;
if (isTileTitle == true) {
textStyle = textTheme.bodyLarge?.copyWith(color: colorScheme.onSurface);
}
if (isTileSubtitle == true) {
textStyle =
textTheme.bodyMedium?.copyWith(color: colorScheme.onSurfaceVariant);
}
if (isTitle == true) {
textStyle = textTheme.titleLarge;
}
if (isPrimaryTitle == true) {
textStyle = textTheme.titleLarge?.copyWith(
color: colorScheme.primary,
);
}
return LayoutBuilder(
builder: (context, constraints) {
final textPainter = TextPainter(
text: TextSpan(text: text, style: textStyle),
textDirection: TextDirection.ltr,
maxLines: 1,
textScaler: textScaler,
)..layout(maxWidth: maxWidth ?? constraints.maxWidth);
return textPainter.didExceedMaxLines
? SizedBox(
height: textPainter.height,
width: maxWidth ?? constraints.maxWidth,
child: Marquee(
text: text,
velocity: 20,
blankSpace: 20,
textScaler: textScaler,
pauseAfterRound: const Duration(seconds: 1),
accelerationDuration: const Duration(seconds: 1),
accelerationCurve: Curves.linear,
decelerationDuration: const Duration(milliseconds: 300),
decelerationCurve: Curves.easeOut,
style: textStyle,
),
)
: Text(
text,
style: textStyle,
maxLines: 1,
overflow: TextOverflow.ellipsis,
);
},
);
}
}
跑马灯
跑马灯也叫 Marquee 元素,常用于在有限的空间中展示更多的信息。
自适应
我们总是希望只有在文本宽度超过可以显示的大小时才显示 Marquee,使用 LayoutBuilder
可以很容易的做到这一点。只需要通过 TextPainter
对需要显示的文本进行渲染,同时限制最大宽度为可用的宽度,如果超出了需要显示的布局范围,就显示为跑马灯组件,否则返回一个普通的 Text
组件。