今天遇到一個(gè)需求懦底,后臺返回字符串和目標(biāo)字符基茵,將目標(biāo)字符上色,在Android中很好實(shí)現(xiàn)根灯,使用TextSpannableString就可以烙肺,但是Flutter中只能使用TextSpan,嘗試了幾種方法后終于實(shí)現(xiàn)搏明。
import 'package:flutter/material.dart';
import 'package:easy_flutter/utils/extension/StringUtils.dart';
class SpannableTextWidget extends StatefulWidget {
final String text;
final List<String> pattern;
final TextStyle defStyle;
final TextStyle patternStyle;
final EdgeInsets margin;
SpannableTextWidget(
{this.text,
this.pattern,
this.defStyle,
this.patternStyle,
this.margin = EdgeInsets.zero});
@override
State<StatefulWidget> createState() => _SpannableTextState();
}
class _SpannableTextState extends State<SpannableTextWidget> {
List<TextSpan> list = [];
List<int> indexList = [];
Map<String, List<int>> _memory = {};
int index = 0;
@override
void initState() {
super.initState();
String t = widget.text;
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
_init(t);
});
}
@override
Widget build(BuildContext context) {
return Container(
margin: widget.margin,
child: list.isEmpty
? Text('')
: Text.rich(
TextSpan(children: list),
),
);
}
_init(String t) {
if (t != null && t.isNotEmpty) {
if (widget.pattern != null && widget.pattern.isNotEmpty) {
widget.pattern.forEach((element) {
if (_memory[element] == null) _memory[element] = [];
while (_calc(t, element) != -1) {}
});
} else {
list.add(TextSpan(text: t, style: widget.defStyle));
}
var charList = t.toCharList();
for (int i = 0; i < charList.length; i++) {
if (indexList.contains(i)) {
list.add(TextSpan(text: charList[i], style: widget.patternStyle));
} else
list.add(TextSpan(text: charList[i], style: widget.defStyle));
}
setState(() {});
}
}
int _calc(String t, String element) {
int indexOf = t.indexOf(
element, _memory[element].isEmpty ? 0 : _memory[element].last + 1);
if (indexOf != -1) {
for (int i = indexOf; i < indexOf + element.length; i++) {
if (!indexList.contains(i)) indexList.add(i);
}
_memory[element].add(indexOf);
}
return indexOf;
}
}
List<String> toCharList() {
return this.runes.map((e) => String.fromCharCode(e)).toList();
}
使用方法
SpannableTextWidget(
text: '11121222211133123453454353412312',
pattern: ["1", "3", "5"],
defStyle: TextStyle(
fontSize: 15, color: Colors.black),
patternStyle: TextStyle(fontSize:18,color:Colors.red),
margin:
EdgeInsets.only(top: 22, left: 20, right: 20),
)
運(yùn)行效果
剛發(fā)群里沒多久,就被大佬教育了娃循,說我寫的太爛炕檩,然后大佬給出了自己的解決方案:
import 'package:flutter/material.dart';
import 'package:easy_flutter/utils/extension/StringUtils.dart';
class SpannableTextWidget extends StatelessWidget {
final String text;
final List<String> pattern;
final TextStyle defStyle;
final TextStyle patternStyle;
final EdgeInsets margin;
SpannableTextWidget(
{this.text,
this.pattern,
this.defStyle,
this.patternStyle,
this.margin = EdgeInsets.zero});
@override
Widget build(BuildContext context) {
RegExp regExp = RegExp('$pattern');
List<TextSpan> list = text
.replaceAllMapped(regExp, (match) => '&*${match[0]}&*')
.split('&*')
.map<TextSpan>((e) => regExp.matchAsPrefix(e) == null
? TextSpan(text: e, style: defStyle)
: TextSpan(text: e, style: patternStyle))
.toList();
return Container(
margin: margin,
child: list.isEmpty
? Text('')
: Text.rich(
TextSpan(children: list),
),
);
}
}