如何将小部件(例如芯片或容器)添加到 flutter 中的文本字段

Pra*_*ell 7 widget textfield flutter

我有一个将由用户填写的文本字段小部件。问题是除了填写文本之外,用户还应该能够从可以添加在文本之间(或结尾)的标签列表中进行选择,示例情况如图所示(在图中我有使用了两个文本小部件和一个芯片,在实际情况下它将是一个文本字段而不是文本小部件)。

在此输入图像描述

这里的解决方案不满足要求,因为它只添加了芯片而不是文本。我还检查了扩展文本字段包,它也不起作用。知道如何解决这个问题吗?

Men*_*elG 2

使用packageextended_text_field包。

结果

每当有一个@符号时,它都会位于Chip

在此输入图像描述

您需要扩展SpecialTextSpanBuilder并覆盖build

class MySpecialTextSpanBuilder extends SpecialTextSpanBuilder {
  @override
  TextSpan build(String data,
      {TextStyle? textStyle, SpecialTextGestureTapCallback? onTap}) {
    final lookingFor = "@";
    final splitData = data.split(" ");
    final spans = splitData.map((e) {
      if (e == lookingFor) {
        return WidgetSpan(
          child: Chip(
            label: Text(e),
          ),
        );
      } else {
        return TextSpan(
          text: e,
          style: TextStyle(color: Colors.red),
        );
      }
    }).toList();
    return TextSpan(children: spans, style: textStyle);
  }

  @override
  SpecialText? createSpecialText(String flag,
      {TextStyle? textStyle,
      SpecialTextGestureTapCallback? onTap,
      required int index}) {
    // TODO: implement createSpecialText
    throw UnimplementedError();
  }
}

Run Code Online (Sandbox Code Playgroud)

在此代码中,如果文本包含@符号,则我们将使用该数据创建Chip,否则,我们将添加实际文本。

使用创建的MySpecialTextSpanBuilder类:

Scaffold(
          backgroundColor: Colors.blue,
          body: ExtendedTextField(
            style: TextStyle(color: Colors.red),
            decoration: InputDecoration(
              border: OutlineInputBorder(),
            ),
            specialTextSpanBuilder: MySpecialTextSpanBuilder(),
          ),
        )
Run Code Online (Sandbox Code Playgroud)

完整的可运行片段:

import 'package:extended_text_field/extended_text_field.dart';
import 'package:flutter/material.dart';

const Color darkBlue = Color.fromARGB(255, 18, 32, 47);

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        dividerColor: Colors.green,
        scaffoldBackgroundColor: darkBlue,
      ),
      debugShowCheckedModeBanner: false,
      home: SafeArea(
        child: Scaffold(
          backgroundColor: Colors.blue,
          body: ExtendedTextField(
            cursorColor: Colors.black,
            style: TextStyle(color: Colors.red),
            decoration: InputDecoration(
              border: OutlineInputBorder(),
            ),
            specialTextSpanBuilder: MySpecialTextSpanBuilder(),
          ),
        ),
      ),
    );
  }
}

class MySpecialTextSpanBuilder extends SpecialTextSpanBuilder {
  @override
  TextSpan build(String data,
      {TextStyle? textStyle, SpecialTextGestureTapCallback? onTap}) {
    final lookingFor = "@";
    final splitData = data.split(" ");
    final spans = splitData.map((e) {
      if (e == lookingFor) {
        return WidgetSpan(
          child: Chip(
            label: Text(e),
          ),
        );
      } else {
        return TextSpan(
          text: e,
          style: TextStyle(color: Colors.red),
        );
      }
    }).toList();
    return TextSpan(children: spans, style: textStyle);
  }

  @override
  SpecialText? createSpecialText(String flag,
      {TextStyle? textStyle,
      SpecialTextGestureTapCallback? onTap,
      required int index}) {
    // TODO: implement createSpecialText
    throw UnimplementedError();
  }
}
Run Code Online (Sandbox Code Playgroud)

使用Text小部件

您可以RichText将 aWidgetSpan作为孩子使用:

内联嵌入文本中的不可变小部件。

结果

在此输入图像描述

代码

RichText(
      text: TextSpan(
        children: [
          TextSpan(
            text: "one",
          ),
          WidgetSpan(
            child: Chip(
              label: Text("two"),
            ),
          ),
          TextSpan(
            text: "three",
          ),
        ],
      ),
    )
Run Code Online (Sandbox Code Playgroud)