有什么方法可以改变字符串中特定单词的颜色吗?
Text("some long string")
现在,我只想为'long'设置颜色。
有人可以告诉我如何以编程方式执行此操作吗?
示例:
我很长,某个变量中的一个非常长的字符串,一个很长的字符串
现在我想把‘长’这个词分开。 我可以分隔简单的字符串来突出显示一个单词,但我不确定如何查找并突出显示该单词的所有情况。
将单词包装在 TextSpan 中并分配
style
属性以更改文本外观并使用 RichText 而不是 Text
RichText( text: TextSpan( text: 'Hello ', style: DefaultTextStyle.of(context).style, children: <TextSpan>[ TextSpan(text: 'bold', style: TextStyle(fontWeight: FontWeight.bold)), TextSpan(text: ' world!'), ], ), )
或使用
Text.rich
构造函数 https://docs.flutter.io/flutter/widgets/Text-class.html
const Text.rich( TextSpan( text: 'Hello', // default text style children: <TextSpan>[ TextSpan(text: ' beautiful ', style: TextStyle(fontStyle: FontStyle.italic)), TextSpan(text: 'world', style: TextStyle(fontWeight: FontWeight.bold)), ], ), )
这是我的代码。
import 'package:flutter/material.dart';
class HighlightText extends StatelessWidget {
final String text;
final String highlight;
final TextStyle style;
final TextStyle highlightStyle;
final Color highlightColor;
final bool ignoreCase;
HighlightText({
Key key,
this.text,
this.highlight,
this.style,
this.highlightColor,
TextStyle highlightStyle,
this.ignoreCase: false,
}) : assert(
highlightColor == null || highlightStyle == null,
'highlightColor and highlightStyle cannot be provided at same time.',
),
highlightStyle = highlightStyle ?? style?.copyWith(color: highlightColor) ?? TextStyle(color: highlightColor),
super(key: key);
@override
Widget build(BuildContext context) {
final text = this.text ?? '';
if ((highlight?.isEmpty ?? true) || text.isEmpty) {
return Text(text, style: style);
}
var sourceText = ignoreCase ? text.toLowerCase() : text;
var targetHighlight = ignoreCase ? highlight.toLowerCase() : highlight;
List<TextSpan> spans = [];
int start = 0;
int indexOfHighlight;
do {
indexOfHighlight = sourceText.indexOf(targetHighlight, start);
if (indexOfHighlight < 0) {
// no highlight
spans.add(_normalSpan(text.substring(start)));
break;
}
if (indexOfHighlight > start) {
// normal text before highlight
spans.add(_normalSpan(text.substring(start, indexOfHighlight)));
}
start = indexOfHighlight + highlight.length;
spans.add(_highlightSpan(text.substring(indexOfHighlight, start)));
} while (true);
return Text.rich(TextSpan(children: spans));
}
TextSpan _highlightSpan(String content) {
return TextSpan(text: content, style: highlightStyle);
}
TextSpan _normalSpan(String content) {
return TextSpan(text: content, style: style);
}
}
扩展zhpoo很棒的answer,这里有一个小部件片段,允许您使用正则表达式(dart 的 RegExp)以编程方式设置/突出显示字符串中的任何内容。
dartpad 演示链接:https://dartpad.dev/d7a0826ed1201f7247fafd9e65979953
class RegexTextHighlight extends StatelessWidget {
final String text;
final RegExp highlightRegex;
final TextStyle highlightStyle;
final TextStyle nonHighlightStyle;
const RegexTextHighlight({
@required this.text,
@required this.highlightRegex,
@required this.highlightStyle,
this.nonHighlightStyle,
});
@override
Widget build(BuildContext context) {
if (text == null || text.isEmpty) {
return Text("",
style: nonHighlightStyle ?? DefaultTextStyle.of(context).style);
}
List<TextSpan> spans = [];
int start = 0;
while (true) {
final String highlight =
highlightRegex.stringMatch(text.substring(start));
if (highlight == null) {
// no highlight
spans.add(_normalSpan(text.substring(start)));
break;
}
final int indexOfHighlight = text.indexOf(highlight, start);
if (indexOfHighlight == start) {
// starts with highlight
spans.add(_highlightSpan(highlight));
start += highlight.length;
} else {
// normal + highlight
spans.add(_normalSpan(text.substring(start, indexOfHighlight)));
spans.add(_highlightSpan(highlight));
start = indexOfHighlight + highlight.length;
}
}
return RichText(
text: TextSpan(
style: nonHighlightStyle ?? DefaultTextStyle.of(context).style,
children: spans,
),
);
}
TextSpan _highlightSpan(String content) {
return TextSpan(text: content, style: highlightStyle);
}
TextSpan _normalSpan(String content) {
return TextSpan(text: content);
}
}
我最近开发了一个名为动态文本突出显示的包。它可以让您以编程方式突出显示给定文本中的某些给定单词。
看看https://pub.dev/packages/dynamic_text_highlighting
示例
Widget buildDTH(String text, List<String> highlights) {
return DynamicTextHighlighting(
text: text,
highlights: highlights,
color: Colors.yellow,
style: TextStyle(
fontSize: 18.0,
fontStyle: FontStyle.italic,
),
caseSensitive: false,
);
}
它是一个无状态小部件,因此对于任何更改,只需调用
setState(() {...})
。
void applyChanges(List<String> newHighlights) {
setState(() {
highlights = newHighlights;
});
}
使用此代码甚至会突出显示查询字母,检查一次
List<TextSpan> highlight(
String main, String query) {
List<TextSpan> children = [];
List<String> abc = query.toLowerCase().split("");
for (int i = 0; i < main.length; i++) {
if (abc.contains(main[i])) {
children.add(TextSpan(
text: main[i],
style: TextStyle(
backgroundColor: Colors.yellow[300],
color: Colors.black,
decoration: TextDecoration.none,
fontFamily: fontName,
fontWeight: FontWeight.bold,
fontSize: 16)));
} else {
children.add(TextSpan(
text: main[i],
style: TextStyle(
color: Colors.black,
decoration: TextDecoration.none,
fontFamily: fontName,
fontWeight: FontWeight.w300,
fontSize: 16)));
}
}
return children;
}
要实现这一目标,有几种可能性:
1- 使用 Text.rich 构造函数而不是 Text 小部件,然后在构造函数内,您将使用 TextSpan 小部件,它允许您通过 style 属性添加样式。第一个 TextSpan 直接位于 Text.rich 中,然后通过其 Children 属性将另一个 TextSpan 放入第一个 TextSpan 中。
Text.rich(
TextSpan(
text: 'Some ',
children: <TextSpan>[
TextSpan(
text: ' Long ',
style: TextStyle(fontWeight: FontWeight.bold , background: Paint()..color = Colors.red)),
TextSpan(
text: ' world',
style: TextStyle(backgroundColor: Colors.yellow)),
],
),
)
输出:
2- 使用 RichText 小部件。与 Text.rich 相同,但这次第一个 TextSpan 将放在 RichText 小部件的 text 属性上。
RichText(
text:TextSpan(
text: 'Some ',
style: TextStyle(color: Colors.blue),
children: <TextSpan>[
TextSpan(
text: ' Long ',
style: TextStyle(color:Colors.black ,fontWeight: FontWeight.bold , background: Paint()..color = Colors.red)),
TextSpan(
text: ' world',
style: TextStyle(backgroundColor: Colors.yellow)),
],
),
)
输出:
3- 外部包的使用。 我建议您highlight_text或substring_highlight
您可以使用这个flutter插件突出显示文本插件。是个不错的选择,值得一试