0

我在 IndexedListView 中使用 FutureBuilder 来显示电话簿列表,

Widget _buildBody(context) {
  String url = api_url_phonebook;
  return Padding(
    padding: const EdgeInsets.symmetric(horizontal: 10.0),
    child: Column(
      children: [
        TextField(
          onTap: () => onTextChanged(_controller.text),
          ...
        ),
        Expanded(
          child: IndexedListView(
            100.0,
            _getData(context, url),
            ...
          ),
        ),
      ],
    ),
  );
}

Future<Either<ResponseError, List<dynamic>>> _getData(context, url) {
  final result = RequestApi(url).fetchList();
  return result;
}

onSearchTextChanged(String text) {
  ...
}

现在我想在 TextField 中输入文本时过滤此电话簿,我该怎么办?

4

1 回答 1

0

我建议你使用委托模式来做到这一点。

创建一个如下所示的类:

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

import 'package:mywallet/model/user_account.dart';
import 'package:mywallet/ui/account_item.dart';

class AccountListSearch extends SearchDelegate {
  final List<UserAccount> newItems;
  String selectedResult = '';
  AccountListSearch(this.newItems);

  bool _match(UserAccount account, String text) {
    return account.name.toLowerCase().contains(text.toLowerCase()) ||
        account.user.toLowerCase().contains(text.toLowerCase());
  }

  @override
  List<Widget> buildActions(BuildContext context) => [
        IconButton(
          icon: Icon(Icons.close),
          onPressed: () {
            query = '';
          },
        ),
      ];

  @override
  Widget buildLeading(BuildContext context) => IconButton(
        icon: Icon(Icons.arrow_back),
        onPressed: () {
          Navigator.pop(context);
        },
      );

  @override
  Widget buildResults(BuildContext context) {
    return Container(
        child: Center(
      child: Text(selectedResult),
    ));
  }

  @override
  Widget buildSuggestions(BuildContext context) {
    var suggestionList = <UserAccount>[];
    query.isEmpty
        ? suggestionList = newItems
        : suggestionList.addAll(
            newItems.where((item) {
              return _match(item, query);
            }),
          );
    return ListView.builder(
      itemCount: suggestionList.length,
      itemBuilder: (context, index) => AccountItem(
        account: suggestionList[index],
      ),
    );
  }
}

复制并粘贴 AccountListSearch 类,仅将 UserAccount 类更改为您的数据类(PhoneBook Item),并将 AccountItem 无状态小部件更改为您用于显示您的 PhoneBook 项目的 Widget(类似于 class PhoneBookItemWidget extends StatelessWidget ......)

然后在这个类的主页中:

class HomePage extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return BlocBuilder<AccountCubit, AccountState>(
      builder: (_, state) {
        var currentState = state;
        if (currentState is InitializedState) {
          var accounts = currentState.userAccounts;
          return Scaffold(
              appBar: AppBar(
                title: Text('All Accounts'),
                actions: [
                  IconButton(
                    onPressed: () {
                      showSearch(
                          context: context,
                          delegate: AccountListSearch(accounts));
                    },
                    icon: Icon(
                      Icons.search,
                    ),
                  )
                ],
              ),
              drawer: AppDrawer(),
              body:    
              ListView.builder(
                       itemCount: accounts.length,
                      itemBuilder: (context, counter) => AccountItem(
                                               account: accounts[counter],
                                               )
....
}

如您所见,“魔术”在方法中:

showSearch( context: context,  delegate: AccountListSearch(accounts));

方法 showSearch(...) 继承自 StatelessWidget 并为您完成所有工作。

我使用了 Bloc 模式,但现在并不重要,只是告诉在哪里可以找到项目列表,但这与您的问题没有直接关系。

于 2020-12-31T09:58:53.277 回答