在Flutter中无法扩展TextField吗?

5
我试图修改一个文本字段,以便我可以在同一文本字段中为特定单词设置不同的颜色。例如,“我想要一个苹果”,单词“苹果”应该是绿色的,其余文本应该是黑色的。
有一些富文本编辑器库(例如zefyr、extended_text_field),但我在stackoverflow上也找到了一个AnnotatedEditableText的示例(https://dev59.com/BVMH5IYBdhLWcg3w3Ejb#57846261)。我喜欢这个最后的解决方案(AnnotatedEditableText),但我想使用TextField来获得更丰富的功能,主要是我无法在只读可编辑文本中使文本选择正常工作。
另外,当将expands: true作为参数设置给TextField时,窗口小部件会正确地扩展以填充区域。但是,当将相同的属性设置为可编辑文本时,什么都不会发生。不确定原因是什么。
因此 - 我想使用具有AnnotatedEditableText窗口小部件的TextField。我能否在不复制整个TextField类的情况下完成这个操作?以下是我收集到的信息:
  • _TextFieldState是私有的,不能被扩展,但是EditableTextState不是私有的,所以该窗口小部件可以被扩展。
  • TextField窗口小部件不支持EditableText窗口小部件的自定义实现。
有什么想法吗?为什么_TextFieldState是私有的,但是EditableTextState不是私有的?

真的很好,@pskink。为什么不把它写成一个答案呢? - J. S.
@JoãoSoares 好的,已完成(甚至支持多颜色;-)) - pskink
是的,我试过了。它似乎运行良好。干得好! - J. S.
@JoãoSoares 谢谢 😉 - pskink
1个回答

16

使用以下控制器:

class FruitColorizer extends TextEditingController {
  final Map<String, TextStyle> mapping;
  final Pattern pattern;

  FruitColorizer(this.mapping) : pattern = RegExp(mapping.keys.map((key) => RegExp.escape(key)).join('|'));
  @override
  TextSpan buildTextSpan({TextStyle style, bool withComposing}) {
    List<InlineSpan> children = [];
    // splitMapJoin is a bit tricky here but i found it very handy for populating children list
    text.splitMapJoin(pattern, 
      onMatch: (Match match) {
        children.add(TextSpan(text: match[0], style: style.merge(mapping[match[0]])));
      },
      onNonMatch: (String text) {
        children.add(TextSpan(text: text, style: style));
      },
    );
    return TextSpan(style: style, children: children);
  }
}

使用它作为:

TextField(
  style: TextStyle(fontSize: 32),
  controller: FruitColorizer({
    'apple': TextStyle(color: Colors.green, decoration: TextDecoration.underline),
    'orange': TextStyle(color: Colors.orange, shadows: kElevationToShadow[2]),
  }),
),

在您的TextField中键入:"我已经吃了两个苹果,一个香蕉和三个橙子"

编辑

如果您只想使用颜色,可以添加命名构造函数:

FruitColorizer.fromColors(Map<String, Color> colorMap)
: this(colorMap.map((text, color) => MapEntry(text, TextStyle(color: color))));

然后像这样使用:

controller: FruitColorizer.fromColors({
  'apple': Colors.green,
  'orange': Colors.orange,
}),

非常感谢!!!顺便说一下,在buildTextSpan中没有调用父方法。我想知道这样做是否可以? - ch271828n
@pskink,谢谢您的回答,但是关于TextField内部带有渐变的文本怎么办呢? - Rodion Mostovoi
1
@RodionMostovoy 使用 foreground 属性(不是 color: - pskink

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接