likes
comments
collection
share

Flutter中用SearchDelegate实现简单的搜索

作者站长头像
站长
· 阅读数 35

在Flutter中,可以使用SearchDelegate来实现搜索功能。SearchDelegate是一个抽象类,用于构建搜索界面和处理搜索操作。通过重写buildActionsbuildLeadingbuildResultsbuildSuggestions等方法,可以定制搜索栏的外观和搜索结果的展示。

在构建搜索界面时,可以使用常见的Flutter控件如AppBarTextFieldListView.builder等来创建搜索框、搜索建议列表和搜索结果展示区域。在buildResults方法中,可以根据用户输入的关键字进行数据过滤和处理,并展示相应的搜索结果。而buildSuggestions方法则用于展示搜索建议,可以根据用户输入的关键字生成相应的建议列表。

除了基本的搜索功能,还可以通过异步加载数据、数据库查询等方式来实现更复杂的搜索功能。例如,可以使用FutureBuilder来展示异步加载的搜索结果,或者使用数据库查询语句来过滤和展示数据库中的数据。

总之,通过使用SearchDelegate,可以方便地实现自定义的搜索功能,并根据具体需求来定制搜索界面和展示效果。这样的搜索功能可以提供给用户更便捷的搜索体验,提高应用的交互性和用户满意度。

下面让我们来看一下具体的实现:

class CustomSearchDelegate extends SearchDelegate {
CustomSearchDelegate({String hintText}) : super(hintText: hintText);
  @override
  List<Widget> buildActions(BuildContext context) {
    // 构建操作按钮,如清除搜索框内容的按钮
  }

  @override
  Widget buildLeading(BuildContext context) {
    // 构建返回按钮
  }

  @override
  Widget buildResults(BuildContext context) {
    // 构建搜索结果视图
  }

  @override
  Widget buildSuggestions(BuildContext context) {
    // 构建搜索建议视图
  }
}

通过传入不同的hintText,可以在构造CustomSearchDelegate实例时设置搜索栏的提示文本。

下面是一个简单的示例,展示如何在 buildResults 方法中实现搜索功能:

class CustomSearchDelegate extends SearchDelegate {
  List<String> data = [
    'Apple',
    'Banana',
    'Cherry',
    'Durian',
    'Elderberry',
    'Fig',
    'Grape',
    'Honeydew',
    'Jackfruit',
    'Kiwi'
  ];

  List<String> searchResults = [];

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

  @override
  Widget buildLeading(BuildContext context) {
    return IconButton(
      icon: Icon(Icons.arrow_back),
      onPressed: () {
        close(context, null);
      },
    );
  }

  @override
  Widget buildResults(BuildContext context) {
    searchResults = data
        .where((item) => item.toLowerCase().contains(query.toLowerCase()))
        .toList();

    return ListView.builder(
      itemCount: searchResults.length,
      itemBuilder: (context, index) {
        return ListTile(
          title: Text(searchResults[index]),
          onTap: () {
            close(context, searchResults[index]);
          },
        );
      },
    );
  }

  @override
  Widget buildSuggestions(BuildContext context) {
    final suggestionList = query.isEmpty
        ? []
        : data
            .where((item) => item.toLowerCase().contains(query.toLowerCase()))
            .toList();

    return ListView.builder(
      itemCount: suggestionList.length,
      itemBuilder: (context, index) {
        return ListTile(
          title: Text(suggestionList[index]),
          onTap: () {
            query = suggestionList[index];
            showResults(context);
          },
        );
      },
    );
  }
}

这只是一个静态的搜索,下面我们来展示一下如何从网络上获取搜索数据并渲染到界面上:

要实现异步搜索功能,你可以使用FutureBuilder来处理异步操作,并根据搜索结果的状态展示不同的界面。

class CustomSearchDelegate extends SearchDelegate {
  Future<List<String>> searchAsync(String query) async {
    // 模拟异步搜索操作,返回一个字符串列表
    await Future.delayed(Duration(seconds: 2));
    return ['Result 1', 'Result 2', 'Result 3'];
  }

  @override
  Widget buildResults(BuildContext context) {
    return FutureBuilder<List<String>>(
      future: searchAsync(query),
      builder: (BuildContext context, AsyncSnapshot<List<String>> snapshot) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          // 数据加载中
          return Center(child: CircularProgressIndicator());
        } else if (snapshot.hasError) {
          // 数据加载错误
          return Center(child: Text('Error: ${snapshot.error}'));
        } else if (snapshot.hasData) {
          // 数据加载成功,展示结果
          final List<String> searchResults = snapshot.data;
          return ListView.builder(
            itemCount: searchResults.length,
            itemBuilder: (BuildContext context, int index) {
              return ListTile(
                title: Text(searchResults[index]),
                onTap: () {
                  // 处理搜索结果的点击事件
                  close(context, searchResults[index]);
                },
              );
            },
          );
        } else {
          // 数据为空
          return Center(child: Text('No results found'));
        }
      },
    );
  }

  // 其他方法...
}

在上述示例中,searchAsync方法模拟了异步的搜索操作,使用Future.delayed来延迟2秒返回结果。在buildResults方法中,使用FutureBuilder来处理异步加载的搜索结果。根据snapshot的不同状态(waitingerrorhasData),展示不同的界面,如加载中的指示器、错误提示或搜索结果列表。

根据你的实际需求,可以在searchAsync方法中执行具体的异步搜索操作,例如从网络请求数据、调用API或查询数据库等。然后,根据异步操作返回的结果,更新snapshot中的数据并展示在界面上。

这样,当用户进行搜索时,搜索结果会在异步加载完成后自动显示;

同时支持模糊查询的时候对关键字高亮显示

TextSpan buildHighlightedText(String text, String searchQuery) {
    final TextStyle normalStyle = TextStyle(
      fontSize: 26.rpx,
      color: Color(0xff373A3E),
      height: 1.2,
    );
    final TextStyle highlightStyle = TextStyle(
      fontSize: 26.rpx,
      color: Color(0xff1077FE),
      fontWeight: Platform.isAndroid ? FontWeight.w500 : FontWeight.w600,
      height: 1.2,
    );

    final List<TextSpan> spans = [];
    final String normalizedText = text.toLowerCase();
    final String normalizedQuery = searchQuery.toLowerCase();
    int startIndex = 0;
    int index;

    while (
        (index = normalizedText.indexOf(normalizedQuery, startIndex)) != -1) {
      if (index > startIndex) {
        spans.add(
          TextSpan(text: text.substring(startIndex, index), style: normalStyle),
        );
      }

      final int endIndex = index + searchQuery.length;
      spans.add(
        TextSpan(text: text.substring(index, endIndex), style: highlightStyle),
      );
      startIndex = endIndex;
    }

    if (startIndex < normalizedText.length) {
      spans.add(
        TextSpan(text: text.substring(startIndex), style: normalStyle),
      );
    }

    return TextSpan(children: spans);
  }
 TextSpan buildNormalText(String text) {
    final TextStyle normalStyle = TextStyle(
      fontSize: 26.rpx,
      color: Color(0xff373A3E),
      height: 1.2,
    );

    return TextSpan(children: [TextSpan(text: text, style: normalStyle)]);
  }

在清空输入框的时候对列表全量显示

 RichText(
              text: searchQuery.isNotEmpty == true
                  ? buildHighlightedText(
                      "${shopModel?.shopNum} ${shopModel?.name}", searchQuery)
                  : buildNormalText("${shopModel?.shopNum} ${shopModel?.name}"),
            ),

异步搜索是在Flutter应用中实现搜索功能的常见需求之一。通过使用FutureBuilder和异步方法,我们可以优雅地处理搜索过程中的异步加载操作。

在实现异步搜索时,关键是将搜索操作封装在一个异步方法中,该方法可以是从网络请求数据、调用API、查询数据库等。使用FutureBuilder来监听异步操作的状态,并根据不同的状态展示相应的界面。

当用户进行搜索时,应用会显示加载中的指示器,以避免阻塞用户界面。一旦异步操作完成,FutureBuilder会根据不同的状态(如waitingerrorhasData)展示不同的界面。这样,我们可以展示搜索结果列表、错误提示或空结果提示,以便用户了解搜索的进度和结果。

通过使用异步搜索,我们可以提供更好的用户体验,使搜索过程在后台进行,不会阻塞应用的其他操作。同时,通过合理地处理异步操作的结果和错误,我们可以向用户提供准确且有意义的搜索结果。

总之,异步搜索在Flutter中是实现搜索功能的重要方式之一。通过结合FutureBuilder和异步方法,我们可以轻松地实现异步搜索。

希望对您有所帮助!!!

转载自:https://juejin.cn/post/7246661279142297661
评论
请登录