Issue
How can I create a Rich Text Input like a Telegram chat page, without displaying reserved characters (such as **
bold**
, _
italic_
) in Text Filed?
src="https://i.stack.imgur.com/rUXGO.jpg" alt="see this screenshot" />
Solution
I found a way to do this by creating a custom TextEditingController
, but reserved characters still exist and are just not visible:
import 'dart:ui';
import 'package:flutter/material.dart';
class RichTextFieldController extends TextEditingController {
late final Pattern pattern;
String pureText = '';
final Map<String, TextStyle> map = {
r'@.\w+': const TextStyle(color: Colors.blue),
r'#.\w+': const TextStyle(color: Colors.blue),
r'\*\*(.*?)\*\*': const TextStyle(fontWeight: FontWeight.bold),
r'__(.*?)__': const TextStyle(fontStyle: FontStyle.italic),
'~~(.*?)~~': const TextStyle(decoration: TextDecoration.lineThrough),
r'```(.*?)```': const TextStyle(
fontFamily: 'mono',
fontFeatures: [FontFeature.tabularFigures()],
)
};
RichTextFieldController() {
pattern = RegExp(map.keys.map((key) => key).join('|'), multiLine: true);
}
@override
set text(String newText) {
value = value.copyWith(
text: newText,
selection: TextSelection.collapsed(offset: newText.length),
composing: TextRange.empty,
);
}
@override
TextSpan buildTextSpan({
required context,
TextStyle? style,
required bool withComposing,
}) {
final List<InlineSpan> children = [];
text.splitMapJoin(
pattern,
onMatch: (Match match) {
String? formattedText;
String? textPattern;
final patterns = map.keys.toList();
if (RegExp(patterns[0]).hasMatch(match[0]!)) {
formattedText = match[0];
textPattern = patterns[0];
} else if (RegExp(patterns[1]).hasMatch(match[0]!)) {
formattedText = match[0];
textPattern = patterns[1];
} else if (RegExp(patterns[2]).hasMatch(match[0]!)) {
formattedText = match[0]!.replaceAll("**", "");
textPattern = patterns[2];
} else if (RegExp(patterns[3]).hasMatch(match[0]!)) {
formattedText = match[0]!.replaceAll("__", "");
textPattern = patterns[3];
} else if (RegExp(patterns[4]).hasMatch(match[0]!)) {
formattedText = match[0]!.replaceAll("~~", "");
textPattern = patterns[4];
} else if (RegExp(patterns[5]).hasMatch(match[0]!)) {
formattedText = match[0]!.replaceAll("```", "");
textPattern = patterns[5];
}
children.add(TextSpan(
text: formattedText,
style: style!.merge(map[textPattern!]),
));
return "";
},
onNonMatch: (String text) {
children.add(TextSpan(text: text, style: style));
return "";
},
);
return TextSpan(style: style, children: children);
}
}
Answered By - Amin
Answer Checked By - Terry (JavaFixing Volunteer)