【问题标题】:How to enable Flutter user to enter tags into a FormBuilderTextField (Flutter Form Builder package)?如何让 Flutter 用户在 FormBuilderTextField(Flutter Form Builder 包)中输入标签?
【发布时间】:2021-03-25 06:54:46
【问题描述】:

我正在使用 flutter_form_builder 包 (link to package on pub.dev) 构建一个表单,并希望让用户能够在 FormBuilderTextField 中输入标签,模仿 StackOverflow 的 UI 来输入标签(下面的屏幕截图)。

简单的FormBuilderTextField,供参考:

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

这个"Flutter - allow user enter hashtags" StackOverflow 问题很有帮助,但并没有真正解决这个问题。

【问题讨论】:

    标签: forms flutter tags


    【解决方案1】:

    您可以使用textfield_tagsflutter 包在您的 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

    【讨论】:

      【解决方案2】:

      我测试了很多选项,最终选择了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
      

      【讨论】:

      【解决方案3】:

      考虑为此功能使用 FormBuilderChipsInput。

      【讨论】:

      • 谢谢,但我认为用户没有办法输入他们自己可能还不存在的标签
      【解决方案4】:

      如果您只有一个带有 Row 的 Container 以及一个“tag_view”小部件怎么办?

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

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

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

      由于您似乎知道颤振,我无代码地回答了这个问题,因此在这里粘贴的代码也很长,但我就是这样做的。

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

      【讨论】:

      • 谢谢@Maritn Ge。我是 Flutter 新手,所以如果你已经构建了代码,请粘贴它。我会尝试你的建议。棘手的部分是在 Flutter Form Builder 包中执行此操作。敬请期待……
      • @MarkGavagan 如果您有任何问题,请随时在 cmets 中问我,我可以在答案中添加代码示例!
      • 再次感谢@Martin Ge。我仔细考虑了这一点,它会使一个包含 8 个问题的表单具有 10 个问题的视觉和空间权重(增加 25%),因此它不适合这种特殊情况。如果我能找到或构建一个好的(紧凑的)解决方案,我会在这里发布。
      • 我不关注。权重为 10 的 8 个问题是什么意思?你所说的一般问题是什么意思?我以为您在连续输入标签/关键字,也许如果我知道您所说的“问题”是什么意思,我可以想出一个更好的解决方案!
      • 对不起,我不清楚。这是表格中的 8 个问题之一。因为您提出的解决方案占用了如此多的空间,所以它可能会使用户感觉表单“沉重”或笨重 25%。另外,我正在使用 material_tag_editor: ^0.0.6 包构建一种方法,如果效果良好,我会在此处发布。谢谢!
      猜你喜欢
      • 2021-03-25
      • 2020-09-13
      • 2021-04-06
      • 2020-06-14
      • 2021-10-26
      • 1970-01-01
      • 1970-01-01
      • 2021-05-05
      • 1970-01-01
      相关资源
      最近更新 更多