简体   繁体   English

为什么 AutoCompleteTextField 在 Flutter 中没有显示任何建议?

[英]Why AutoCompleteTextField is not showing any suggestion in Flutter?

I am new to Flutter and currently working on a project where I need to show user a list of matched members so that a user can easily select one of them.我是 Flutter 的新手,目前正在从事一个项目,我需要向用户显示匹配成员的列表,以便用户可以轻松地 select 其中一个。 For that I use AutoCompleteTextField.为此,我使用 AutoCompleteTextField。 It is working fine as long as provided by already fetched list of members to it's suggestion property.只要已经获取的成员列表提供给它的建议属性,它就可以正常工作。 But I wonder, why it's not working when I put it under BlocBuilder.但我想知道,为什么当我把它放在 BlocBuilder 下时它不起作用。 Event hits on textChanged method and the state also returns a list but the suggestions are invisible.事件命中 textChanged 方法和 state 也返回一个列表,但建议是不可见的。

  Widget autoCompleteSearchBar() {
    return BlocBuilder<OrderInfoBloc, MyOrderInfoStates>(
      builder: (context, state) {
          return AutoCompleteTextField<Member>(
            clearOnSubmit: false,
            style: TextStyle(
              color: Colors.black,
              fontSize: 16,
            ),
            decoration: InputDecoration(
              hintText: 'Search Member Here..',
              border: InputBorder.none,
              suffixIcon: IconButton(
                icon: Icon(Icons.cancel),
                iconSize: 20,
                color: Colors.yellow[700],
                onPressed: () {
                  _autoCompleteController.text = "";
                },
              ),
              contentPadding: EdgeInsets.fromLTRB(10, 30, 10, 20),
              hintStyle: TextStyle(color: Colors.grey),
            ),
            keyboardType: TextInputType.text,
            controller: _autoCompleteController,
            textChanged: (value) {
              context.read<OrderInfoBloc>().add(SearchTextChanged(text: value));
            },
            itemSubmitted: (item) async {
              _autoCompleteController.text = state.radioGroupValue == 'By Code'
                  ? item.memberNo
                  : item.memberName;
              context.read<OrderInfoBloc>().add(SelectedMember(member: item));
            },
            key: _key,
            suggestions: state.membersList,
            itemBuilder: (context, item) {
              print(item);
              // return state.radioGroupValue == 'By Code'
              //     ? autoCompleteSearchBarRow(
              //         item: item.memberNo, icon: Icon(Icons.person))
              //     : autoCompleteSearchBarRow(
              //         item: item.memberName, icon: Icon(Icons.person));
              return autoCompleteSearchBarRow(
                  item: item.memberNo, icon: Icon(Icons.person));
            },
            itemFilter: (item, query) {
              print(query);
              // bool _itemFilter;
              // if (_autoCompleteController.text.isNotEmpty) {
              //   _itemFilter = state.radioGroupValue == 'By Code'
              //       ? item.memberNo
              //           .toLowerCase()
              //           .startsWith(query.toLowerCase())
              //       : item.memberName
              //           .toLowerCase()
              //           .startsWith(query.toLowerCase());
              // } else {
              //   _autoCompleteController.text = '';
              //   _itemFilter = false;
              // }
              // return _itemFilter;
              return item.memberNo.toLowerCase().startsWith(query.toLowerCase());
            },
            itemSorter: (a, b) {
              // return state.radioGroupValue == 'By Code'
              //     ? a.memberNo.compareTo(b.memberNo.toLowerCase())
              //     : a.memberName.compareTo(b.memberName.toLowerCase());
              print(b);
              return a.memberNo.compareTo(b.memberNo.toLowerCase());
            },
          );
        }
    );
  }

  Widget autoCompleteSearchBarRow(
      {@required String item, @required Icon icon}) {
    return ListTile(
      leading: icon,
      title: Text(item),
    );
  }

Use the flutter_typeahead package which works well with flutter bloc使用flutter_typeahead package,它适用于flutter bloc

Now, come to the bloc side you don't need to wrap your autocomplete widget with blocbuilder cause if you do so, the bloc will always repaint the widget whenever an event fires.现在,来到 bloc 方面,您不需要使用 blocbuilder 包装您的自动完成小部件,因为如果您这样做,那么每当事件触发时,bloc 总是会重新绘制小部件。 so in your case when you are typing in the text box, event fires and bloc rebuild the widget and because of that suggestion don't show up and even if you see suggestion they will be gone once the corresponding bloc state occurs and rebuild the widget因此,在您的情况下,当您在文本框中输入时,事件会触发并 bloc 重建小部件,并且由于该建议不会出现,即使您看到建议,一旦相应的 bloc state 发生并重建小部件,它们也会消失

the recommended solution would be seen below推荐的解决方案如下所示

Don't add any state to get suggestions just return the result or records from event as below.不要添加任何 state 来获取建议,只需从事件中返回结果或记录,如下所示。 (below function added to Cubit file) (以下 function 添加到 Cubit 文件)

  Future<List<Item>> getProductItemsBySearchString(String item) async {
    return await itemRepository.getItemsByName(item);
  }

as you can see above I am returning item records directly from the getProductItemsBySearchString() event method (no bloc state)正如您在上面看到的,我直接从 getProductItemsBySearchString() 事件方法返回项目记录(无 bloc 状态)

Then use It like below然后像下面这样使用它

class ItemScreen extends StatelessWidget {
  // then you can call bloc event in function as below
  Future<List<Item>> getItemSuggestionsList(
      BuildContext context, String text) async {
    final bloc = context.read<ItemCubit>();

    List<Item> data = await bloc.getProductItemsBySearchString(text);

    if (data != null) {
      return data;
    } else {
      return null;
    }
  }

  @override
  Widget build(BuildContext context) {
    return TypeAheadField(
      getImmediateSuggestions: true,
      textFieldConfiguration: TextFieldConfiguration(
          controller: _itemEditingController,
          autofocus: false),
      suggestionsCallback: (pattern) {
        // call the function to get suggestions based on text entered
        return getItemSuggestionsList(context, pattern);
      },
      itemBuilder: (context, suggestion) {
        // show suggection list
        return Padding(
          padding: const EdgeInsets.all(8.0),
          child: ListTile(
            title: Text(suggestion.name),
            trailing: Text(
              'Item Code: ${suggestion.code}',
            ),
          ),
        );
      },
      onSuggestionSelected: (suggestion) {
       // get selected suggesion
      },
    );
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM