Flutter 2:带有 TextPainter 的渐变文本在列中中断
Flutter 2: Gradient Text with TextPainter breaking in Column
我遇到了我的个人 GradientText 问题,它不使用 ShaderMask。
这里是我使用的设备:
我是这样称呼它的:
Column(
children: [
GradientText(
'Party Lopes',
const LinearGradient(
colors: <Color>[
Color.fromARGB(255, 227, 82, 0),
Color.fromARGB(255, 244, 176, 0)
],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
style: TextStyle(
fontWeight: FontWeight.w500
),
),
],
)
这里是我的小部件的代码:
import 'package:flutter/material.dart';
class GradientText extends StatelessWidget {
final String text;
final TextStyle style;
final Gradient? gradient;
final int? maxLine;
const GradientText(
this.text,
{
@required this.gradient,
this.style = const TextStyle(),
this.maxLine = 1,
Key? key,
}
) : super(key: key);
@override
Widget build(BuildContext context) {
final TextPainter _painter = TextPainter(
maxLines: maxLine,
textDirection: TextDirection.rtl,
text: TextSpan(
text: text,
style: style
),
);
_painter.layout();
print(_painter.size);
return CustomPaint(
size: _painter.size,
painter: _GradientTextPainter(
text: text,
style: style,
gradient: gradient,
maxLine: maxLine
),
);
}
}
class _GradientTextPainter extends CustomPainter {
final Gradient? gradient;
final String? text;
final TextStyle? style;
final int? maxLine;
_GradientTextPainter({
Listenable? repaint,
@required this.text,
@required this.style,
@required this.gradient,
@required this.maxLine,
}) : super(repaint: repaint);
@override
void paint(Canvas canvas, Size size) {
final Paint _gradientShaderPaint = Paint()
..shader = gradient != null ?
gradient!.createShader(
Offset.zero & size
) :
null;
final TextPainter _textPainter = TextPainter(
maxLines: maxLine,
textDirection: TextDirection.ltr,
text: TextSpan(
text: text!,
style: TextStyle(
foreground: _gradientShaderPaint,
fontSize: style!.fontSize,
fontWeight: style!.fontWeight,
height: style!.height,
decoration: style!.decoration,
decorationColor: style!.decorationColor,
decorationStyle: style!.decorationStyle,
fontStyle: style!.fontStyle,
letterSpacing: style!.letterSpacing,
fontFamily: style!.fontFamily,
locale: style!.locale,
textBaseline: style!.textBaseline,
wordSpacing: style!.wordSpacing,
),
)
);
_textPainter.layout(
minWidth: 0,
maxWidth: size.width,
);
_textPainter.paint(
canvas,
Offset(
(size.width - _textPainter.width) / 2,
(size.height - _textPainter.height) / 2
)
);
}
@override
bool shouldRepaint(_GradientTextPainter oldDelegate) {
return gradient != oldDelegate.gradient || text != oldDelegate.text ||
style != oldDelegate.style;
}
}
这里给出了这个结果:
而它应该给出这个结果:
所以我不明白为什么它不显示整个文本,我不明白为什么当我将 'Party Lo' 作为文本参数传递时它显示它。
而且我也不明白为什么当我将 maxLines 更改为 2 时,它会把它放在我的第一行下面,而已经有这么多 space 可用
有人可以帮助解决这些问题吗?
这是我想要的结果:
我稍微简化了你的 _GradientTextPainter
并且还添加了可选的 alignment
属性 到 GradientText
- 如果传入的大小限制没有限制(宽度或高度是未设置)然后它需要最小的固有大小来绘制自己,否则 alignment
用于在大小的父窗口小部件内对齐 GradientText
:
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
class GradientText extends StatelessWidget {
final String text;
final TextStyle style;
final Gradient gradient;
final int maxLines;
final Alignment alignment;
final String ellipsis;
const GradientText(
this.text,
this.gradient,
{
this.style = const TextStyle(),
this.maxLines = 1,
this.alignment = Alignment.centerLeft,
this.ellipsis = '\u2026',
Key? key,
}
) : super(key: key);
@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, constraints) {
final TextPainter textPainter = TextPainter(
maxLines: maxLines,
textDirection: TextDirection.ltr,
text: TextSpan(
text: text,
style: style,
),
ellipsis: ellipsis,
);
textPainter.layout(
maxWidth: constraints.maxWidth,
);
final bounded = constraints.hasBoundedHeight &&
constraints.hasBoundedWidth;
final size = bounded? constraints.biggest : textPainter.size;
// print('constraints.biggest: ${constraints.biggest},
// textPainter.size: ${textPainter.size}');
// print('incoming constraints are ${bounded? "" : "NOT "}bounded,
// using ${bounded? "constraint\'s" : "text"} size: $size');
return CustomPaint(
painter: _GradientTextPainter(
text: text,
style: style,
gradient: gradient,
textPainter: textPainter,
alignment: alignment,
),
size: size,
);
}
);
}
}
class _GradientTextPainter extends CustomPainter {
final Gradient gradient;
final String text;
final TextStyle style;
final TextPainter textPainter;
final Alignment alignment;
_GradientTextPainter({
Listenable? repaint,
required this.text,
required this.style,
required this.gradient,
required this.textPainter,
required this.alignment,
}) : super(repaint: repaint);
@override
void paint(Canvas canvas, Size size) {
final textSpanRect = alignment.inscribe(
textPainter.size,
Offset.zero & size
);
// print('=== $size * $alignment => $textSpanRect');
if (debugPaintSizeEnabled)
debugPaintPadding(canvas, textSpanRect, textSpanRect.deflate(2));
textPainter.text = TextSpan(
text: text,
style: style.copyWith(
foreground: Paint()..shader = gradient.createShader(textSpanRect),
),
);
textPainter.layout(
minWidth: 0,
maxWidth: size.width,
);
textPainter.paint(canvas, textSpanRect.topLeft);
}
@override
bool shouldRepaint(_GradientTextPainter oldDelegate) {
return gradient != oldDelegate.gradient || text != oldDelegate.text ||
style != oldDelegate.style;
}
}
我遇到了我的个人 GradientText 问题,它不使用 ShaderMask。
这里是我使用的设备:
我是这样称呼它的:
Column(
children: [
GradientText(
'Party Lopes',
const LinearGradient(
colors: <Color>[
Color.fromARGB(255, 227, 82, 0),
Color.fromARGB(255, 244, 176, 0)
],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
style: TextStyle(
fontWeight: FontWeight.w500
),
),
],
)
这里是我的小部件的代码:
import 'package:flutter/material.dart';
class GradientText extends StatelessWidget {
final String text;
final TextStyle style;
final Gradient? gradient;
final int? maxLine;
const GradientText(
this.text,
{
@required this.gradient,
this.style = const TextStyle(),
this.maxLine = 1,
Key? key,
}
) : super(key: key);
@override
Widget build(BuildContext context) {
final TextPainter _painter = TextPainter(
maxLines: maxLine,
textDirection: TextDirection.rtl,
text: TextSpan(
text: text,
style: style
),
);
_painter.layout();
print(_painter.size);
return CustomPaint(
size: _painter.size,
painter: _GradientTextPainter(
text: text,
style: style,
gradient: gradient,
maxLine: maxLine
),
);
}
}
class _GradientTextPainter extends CustomPainter {
final Gradient? gradient;
final String? text;
final TextStyle? style;
final int? maxLine;
_GradientTextPainter({
Listenable? repaint,
@required this.text,
@required this.style,
@required this.gradient,
@required this.maxLine,
}) : super(repaint: repaint);
@override
void paint(Canvas canvas, Size size) {
final Paint _gradientShaderPaint = Paint()
..shader = gradient != null ?
gradient!.createShader(
Offset.zero & size
) :
null;
final TextPainter _textPainter = TextPainter(
maxLines: maxLine,
textDirection: TextDirection.ltr,
text: TextSpan(
text: text!,
style: TextStyle(
foreground: _gradientShaderPaint,
fontSize: style!.fontSize,
fontWeight: style!.fontWeight,
height: style!.height,
decoration: style!.decoration,
decorationColor: style!.decorationColor,
decorationStyle: style!.decorationStyle,
fontStyle: style!.fontStyle,
letterSpacing: style!.letterSpacing,
fontFamily: style!.fontFamily,
locale: style!.locale,
textBaseline: style!.textBaseline,
wordSpacing: style!.wordSpacing,
),
)
);
_textPainter.layout(
minWidth: 0,
maxWidth: size.width,
);
_textPainter.paint(
canvas,
Offset(
(size.width - _textPainter.width) / 2,
(size.height - _textPainter.height) / 2
)
);
}
@override
bool shouldRepaint(_GradientTextPainter oldDelegate) {
return gradient != oldDelegate.gradient || text != oldDelegate.text ||
style != oldDelegate.style;
}
}
这里给出了这个结果:
而它应该给出这个结果:
所以我不明白为什么它不显示整个文本,我不明白为什么当我将 'Party Lo' 作为文本参数传递时它显示它。
而且我也不明白为什么当我将 maxLines 更改为 2 时,它会把它放在我的第一行下面,而已经有这么多 space 可用
有人可以帮助解决这些问题吗?
这是我想要的结果:
我稍微简化了你的 _GradientTextPainter
并且还添加了可选的 alignment
属性 到 GradientText
- 如果传入的大小限制没有限制(宽度或高度是未设置)然后它需要最小的固有大小来绘制自己,否则 alignment
用于在大小的父窗口小部件内对齐 GradientText
:
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
class GradientText extends StatelessWidget {
final String text;
final TextStyle style;
final Gradient gradient;
final int maxLines;
final Alignment alignment;
final String ellipsis;
const GradientText(
this.text,
this.gradient,
{
this.style = const TextStyle(),
this.maxLines = 1,
this.alignment = Alignment.centerLeft,
this.ellipsis = '\u2026',
Key? key,
}
) : super(key: key);
@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, constraints) {
final TextPainter textPainter = TextPainter(
maxLines: maxLines,
textDirection: TextDirection.ltr,
text: TextSpan(
text: text,
style: style,
),
ellipsis: ellipsis,
);
textPainter.layout(
maxWidth: constraints.maxWidth,
);
final bounded = constraints.hasBoundedHeight &&
constraints.hasBoundedWidth;
final size = bounded? constraints.biggest : textPainter.size;
// print('constraints.biggest: ${constraints.biggest},
// textPainter.size: ${textPainter.size}');
// print('incoming constraints are ${bounded? "" : "NOT "}bounded,
// using ${bounded? "constraint\'s" : "text"} size: $size');
return CustomPaint(
painter: _GradientTextPainter(
text: text,
style: style,
gradient: gradient,
textPainter: textPainter,
alignment: alignment,
),
size: size,
);
}
);
}
}
class _GradientTextPainter extends CustomPainter {
final Gradient gradient;
final String text;
final TextStyle style;
final TextPainter textPainter;
final Alignment alignment;
_GradientTextPainter({
Listenable? repaint,
required this.text,
required this.style,
required this.gradient,
required this.textPainter,
required this.alignment,
}) : super(repaint: repaint);
@override
void paint(Canvas canvas, Size size) {
final textSpanRect = alignment.inscribe(
textPainter.size,
Offset.zero & size
);
// print('=== $size * $alignment => $textSpanRect');
if (debugPaintSizeEnabled)
debugPaintPadding(canvas, textSpanRect, textSpanRect.deflate(2));
textPainter.text = TextSpan(
text: text,
style: style.copyWith(
foreground: Paint()..shader = gradient.createShader(textSpanRect),
),
);
textPainter.layout(
minWidth: 0,
maxWidth: size.width,
);
textPainter.paint(canvas, textSpanRect.topLeft);
}
@override
bool shouldRepaint(_GradientTextPainter oldDelegate) {
return gradient != oldDelegate.gradient || text != oldDelegate.text ||
style != oldDelegate.style;
}
}