如何让 Flutter 用户将标签输入 FormBuilderTextField(Flutter Form Builder 包)?

How to enable Flutter user to enter tags into a FormBuilderTextField (Flutter Form Builder package)?

我正在使用 flutter_form_builder 包 (link to package on pub.dev) 构建表单,并希望允许用户将标签输入 FormBuilderTextField,模仿 Whosebug 的 UI 输入标签(下面的屏幕截图)。

简单的FormBuilderTextField,供参考:

FormBuilderTextField(
                      attribute: 'sampleAttribute',
                      decoration: InputDecoration(
                        labelText: "  Separate items,  with,  commas",
                        labelStyle: TextStyle(
                          fontSize: 12.0,
                          fontStyle: FontStyle.italic,
                        ),
                      ),
                    ),

这个 Whosebug 问题很有帮助,但并没有真正解决这个问题。

如果您只有一个带行的容器以及一个 'tag_view' 小部件怎么办?

容器会像 Whosebug 一样有边框。该行是可滚动的并且有多个项目:

用户添加的每个标签和一个输入字段。每次用户接受标签时,您都会将其添加到标签列表中。

为此,您只需要一个带有包含不同 TagView 的小部件列表的行,并且在右边总是有一个 TextField

既然你似乎知道 flutter,我就不用代码来回答这个问题,而且粘贴在这里的代码也很长,但我就是这样做的。

推荐的标签会很容易处理,您只需将它们全部放在一个堆栈中,然后在顶部放置一个视图列表,其中包含推荐的标签以及您想要的任何视图

考虑使用 FormBuilderChipsInput 实现此功能。

我测试了很多选项并选择了 material_tag_editor 0.0.6 Flutter package

这是 iPhone 模拟器 输入任何标签之前的屏幕截图:

这是输入了两个标签(使用逗号作为分隔符)的屏幕截图,同时正在输入第三个标签:

代码如下:

body: SingleChildScrollView(
    child: Container(
      child: Builder(
        builder: (context) => FormBuilder(
          // was "builder: (context) => Form("
          key: _formbuilderKey,
          initialValue: {
            'date': DateTime.now(),
          },
          child: Padding(
            padding: const EdgeInsets.all(14.0),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                SizedBox(
                  height: 12.0,
                ),
                RichText(
                  text: TextSpan(
                    style: TextStyle(
                      color: Colors.blue,
                    ),
                    children: <TextSpan>[
                      TextSpan(
                        text:
                            'In just a few words, what are 3 positive things about dogs?', // was 'What are 3 good or positive things about the house, property or neighborhood?', //  [ 1 ​]
                        style: TextStyle(
                          fontWeight: FontWeight.bold,
                          fontSize: 16.0,
                        ),
                      ),
                      TextSpan(
                        text: '  (optional)',
                        style: TextStyle(
                          fontWeight: FontWeight.normal,
                          fontStyle: FontStyle.italic,
                          fontSize: 14.0,
                          color: Colors.black54,
                        ), // was 'misleading or inaccurate?',
                      ),
                    ],
                  ),
                ),
                // BEGIN code from material_tag_editor
                Padding(
                  padding: const EdgeInsets.only(top: 16.0),
                  child: TagEditor(
                    length: somethingHere.length,
                    delimiters: [
                      ','
                    ], // was delimiters: [',', ' '],  Also tried "return" ('\u2386',)
                    hasAddButton: true,
                    textInputAction: TextInputAction
                        .next, // moves user from one field to the next!!!!
                    autofocus: false,
                    maxLines: 1,
                    // focusedBorder: OutlineInputBorder(
                    //   borderSide: BorderSide(color: Colors.lightBlue),
                    //   borderRadius: BorderRadius.circular(20.0),
                    // ),
                    inputDecoration: const InputDecoration(
                      // below was "border: InputBorder.none,"
                      isDense: true,
                      border: OutlineInputBorder(
                        borderRadius: const BorderRadius.all(
                          const Radius.circular(20.0),
                        ),
                      ),
                      focusedBorder: OutlineInputBorder(
                        borderSide: BorderSide(color: Colors.lightBlue),
                        borderRadius: const BorderRadius.all(
                          const Radius.circular(20.0),
                        ),
                        // above is per https://github.com/flutter/flutter/issues/5191
                      ),
                      labelText: 'separate,  with,  commas',
                      labelStyle: TextStyle(
                        fontStyle: FontStyle.italic,
                        backgroundColor:
                            Color(0x65dffd02), // was Color(0xffDDFDFC),
                        color: Colors.black87, // was Color(0xffD82E6D),
                        fontSize: 14,
                      ),
                    ),
                    onTagChanged: (newValue) {
                      setState(() {
                        somethingHere.add(newValue);
                      });
                    },
                    tagBuilder: (context, index) => _Chip(
                      index: index,
                      label: somethingHere[index],
                      onDeleted: onDelete,
                    ),
                  ),
                ),
                // END code from material_tag_editor

您可以使用 textfield_tags flutter 包在您的 Flutter 应用中实现此功能。请参阅以下示例:

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

  void main() {
    runApp( MaterialApp(
        home: Home()
    ));
  }

  class Home extends  StatefulWidget {
    @override
    State<Home> createState() => _HomeState();
  }

  class _HomeState extends State<Home> {

    List<String> tags = ["flutter", "fluttercampus"]; //initial tags

    @override
    Widget build(BuildContext context) {
      return Scaffold(
          appBar: AppBar(
              title: Text("Enable Tag Input in TextField"),
              backgroundColor: Colors.redAccent,
          ),
            body: Container(
              alignment: Alignment.center,
              padding: EdgeInsets.all(20),
              child: Column(
                children:[
                      TextFieldTags(
                        textSeparators: [ 
                            " ", //seperate with space
                            ',' //sepearate with comma as well
                                
                        ],
                        initialTags: tags,
                        onTag: (tag){
                            print(tag);
                            //this will give tag when entered new single tag
                            tags.add(tag);
                        },
                        onDelete: (tag){
                            print(tag);
                            //this will give single tag on delete
                            tags.remove(tag);
                        },
                        validator: (tag){
                            //add validation for tags
                            if(tag.length < 3){
                                return "Enter tag up to 3 characters.";
                            }
                            return null;
                        },
                        tagsStyler: TagsStyler( //styling tag style
                            tagTextStyle: TextStyle(fontWeight: FontWeight.normal),
                              tagDecoration: BoxDecoration(color: Colors.blue[100], borderRadius: BorderRadius.circular(0.0), ),
                              tagCancelIcon: Icon(Icons.cancel, size: 18.0, color: Colors.blue[900]),
                              tagPadding: EdgeInsets.all(6.0)
                        ),
                        textFieldStyler: TextFieldStyler( //styling tag text field
                              textFieldBorder: OutlineInputBorder(
                                borderSide: BorderSide(color: Colors.blue, width: 2)
                              )
                        ),
                      ),

                      ElevatedButton(
                        onPressed: (){
                          print(tags);
                          //pint list of tags int the TextField
                        }, 
                        child: Text("Print Entered Tags")
                      )
                ]
              ),
            )
        );
    }
  }

此代码的输出:

在此处获取示例:How to Make Tags Input on TextField in Flutter