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

Why AutoCompleteTextField is not showing any suggestion in Flutter?

我是 Flutter 的新手,目前正在做一个项目,我需要向用户显示匹配成员的列表,以便用户可以轻松地 select 其中之一。为此,我使用 AutoCompleteTextField。只要已经获取的成员列表提供给它的建议 属性,它就可以正常工作。但我想知道,为什么当我把它放在 BlocBuilder 下时它不起作用。事件命中 textChanged 方法,状态也是 returns 列表,但建议是不可见的。

  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),
    );
  }

使用与 flutter bloc 配合良好的 flutter_typeahead

现在,来到集团方面,您不需要使用 blocbuilder 包装您的自动完成小部件,因为如果您这样做,集团将始终在事件触发时重新绘制小部件。因此,在您的情况下,当您在文本框中键入内容时,事件会触发并 bloc 重建小部件,并且由于该建议不会显示,即使您看到建议,一旦相应的 bloc 状态发生并重建小部件,它们也会消失

推荐的解决方案如下所示

不要添加任何状态以获得建议,仅 return 事件的结果或记录如下。 (以下功能已添加到 Cubit 文件中)

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

正如您在上面看到的那样,我 return 直接从 getProductItemsBySearchString() 事件方法(无 bloc 状态)获取商品记录

然后像下面这样使用它

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
      },
    );
  }
}