Files
UnionApp/lib/tool/gradientText.dart
spasolreisa 9ce601aa8d initial
2026-04-16 14:26:52 +08:00

117 lines
3.4 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:flutter/material.dart';
class GradientLayer {
final Gradient gradient;
final BlendMode blendMode;
const GradientLayer({
required this.gradient,
this.blendMode = BlendMode.srcIn, // 默认第一层用 srcIn 打底
});
}
class GradientText extends StatelessWidget {
final String data;
final TextStyle? style;
final TextAlign? textAlign;
final TextDirection? textDirection;
final bool softWrap;
final TextOverflow? overflow;
final double? textScaleFactor;
final int? maxLines;
final Locale? locale;
final String? semanticsLabel;
final TextWidthBasis? textWidthBasis;
final TextHeightBehavior? textHeightBehavior;
final List<GradientLayer> gradientLayers;
const GradientText({
Key? key,
required this.data,
this.style,
this.textAlign,
this.textDirection,
this.softWrap = true,
this.overflow,
this.textScaleFactor,
this.maxLines,
this.locale,
this.semanticsLabel,
this.textWidthBasis,
this.textHeightBehavior,
this.gradientLayers = const [],
}) : super(key: key);
@override
Widget build(BuildContext context) {
if (gradientLayers.isEmpty) {
return Text(
data,
style: style,
textAlign: textAlign,
textDirection: textDirection,
softWrap: softWrap,
overflow: overflow,
textScaleFactor: textScaleFactor,
maxLines: maxLines,
locale: locale,
semanticsLabel: semanticsLabel,
textWidthBasis: textWidthBasis,
textHeightBehavior: textHeightBehavior,
);
}
final baseStyle = style ?? const TextStyle();
return Stack(
children: [
// 1. 最底层:纯色文本(可选,防止所有渐变都透明时看不见)
// 如果第一层渐变是 srcIn这一层其实可以被遮挡但保留它作为“备用底色”
Opacity(
opacity: 0.0, // 隐藏,仅占位
child: _buildText(baseStyle.copyWith(color: Colors.black)),
),
// 2. 叠加渐变层
...gradientLayers.asMap().entries.map((entry) {
final index = entry.key;
final layer = entry.value;
// 关键逻辑:
// 如果是第一层且用户没改 blendMode默认用 srcIn 确保文字有颜色
// 如果是后续层,通常希望融合,所以建议用户传入 overlay/plus 等
return ShaderMask(
shaderCallback: (Rect bounds) {
return layer.gradient.createShader(bounds);
},
blendMode: layer.blendMode,
child: _buildText(
// 重要:为了融合效果,内部文本通常是白色或浅色
// 如果 blendMode 是 srcIn颜色不重要会被渐变替换
// 如果 blendMode 是 overlay/plus白色能让渐变颜色最纯正地显示
baseStyle.copyWith(color: Colors.white),
),
);
}).toList(),
],
);
}
Widget _buildText(TextStyle effectiveStyle) {
return Text(
data,
style: effectiveStyle,
textAlign: textAlign,
textDirection: textDirection,
softWrap: softWrap,
overflow: overflow,
textScaleFactor: textScaleFactor,
maxLines: maxLines,
locale: locale,
semanticsLabel: semanticsLabel,
textWidthBasis: textWidthBasis,
textHeightBehavior: textHeightBehavior,
);
}
}