如何在 Flutter 中创建类似 Telegram 或 WhatsApp 聊天页面的富文本输入?

Ami*_*min 3 linux windows android dart flutter

如何创建像 Telegram 聊天页面一样的富文本输入,而不在文本字段中 显示保留字符(例如**粗体**_斜体)?_看这个截图

Ami*_*min 6

我找到了一种通过创建自定义字符来做到这一点的方法TextEditingController,但保留字符仍然存在并且只是不可见:

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);
  }
}
Run Code Online (Sandbox Code Playgroud)