Flutter搜索功能插件searchfield的使用

发布于 1周前 作者 yibo5220 来自 Flutter

Flutter搜索功能插件searchfield的使用

插件概述

searchfield 是一个高度可定制、简单易用的自动完成组件,适用于Flutter应用。该组件允许用户:

  • 搜索🔍并从建议列表中选择
  • 使用自定义验证逻辑验证输入
  • 动态调整每个建议项的高度
  • 显示自定义类型的建议(而不仅仅是字符串)
  • 从网络懒加载建议,并显示自定义加载组件
  • 在输入框上方或下方动态显示建议
  • 定义视口中可见的最大项目数📱
  • 使用自定义逻辑过滤建议
  • 视觉上自定义输入和建议
  • 使用键盘在桌面端导航建议
  • 监听建议滚动事件

开始使用

安装

  1. 添加依赖
flutter pub add searchfield
  1. 导入包
import 'package:searchfield/searchfield.dart';
  1. 使用组件

示例代码

以下是使用searchfield插件创建一个带有国家列表的搜索框的完整示例。

示例:国家搜索

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

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter App',
      theme: ThemeData(
        colorSchemeSeed: Colors.indigo,
        useMaterial3: true,
        brightness: Brightness.light,
      ),
      darkTheme: ThemeData(
        colorSchemeSeed: Colors.blue,
        useMaterial3: true,
        brightness: Brightness.dark,
      ),
      home: SearchFieldSample(),
      debugShowCheckedModeBanner: false,
    );
  }
}

class SearchFieldSample extends StatefulWidget {
  const SearchFieldSample({Key? key}) : super(key: key);

  @override
  State<SearchFieldSample> createState() => _SearchFieldSampleState();
}

class _SearchFieldSampleState extends State<SearchFieldSample> {
  List<String> suggestions = [
    'United States',
    'Germany',
    'Canada',
    'United Kingdom',
    'France',
    'Italy',
    'Spain',
    'Australia',
    'India',
    'China',
    'Japan',
    'Brazil',
    'South Africa',
    'Mexico',
    'Argentina',
    'Russia',
    'Indonesia',
    'Turkey',
    'Saudi Arabia',
    'Nigeria',
    'Egypt',
  ];

  var selectedValue;

  @override
  Widget build(BuildContext context) {
    Widget searchChild(String x, {bool isSelected = false}) => Padding(
          padding: const EdgeInsets.symmetric(horizontal: 12),
          child: Text(x,
              style: TextStyle(
                  fontSize: 18,
                  color: isSelected ? Colors.green : Colors.black)),
        );

    return Scaffold(
      appBar: AppBar(title: Text('Searchfield Demo')),
      body: Padding(
        padding: const EdgeInsets.all(8.0),
        child: ListView(
          children: [
            SearchField(
              suggestionDirection: SuggestionDirection.flex,
              onSearchTextChanged: (query) {
                final filter = suggestions
                    .where((element) =>
                        element.toLowerCase().contains(query.toLowerCase()))
                    .toList();
                return filter
                    .map((e) => SearchFieldListItem<String>(e, child: searchChild(e)))
                    .toList();
              },
              selectedValue: selectedValue,
              autovalidateMode: AutovalidateMode.onUserInteraction,
              validator: (value) {
                if (value == null || !suggestions.contains(value.trim())) {
                  return 'Enter a valid country name';
                }
                return null;
              },
              onSubmit: (x) {},
              autofocus: false,
              key: const Key('searchfield'),
              hint: 'Search by country name',
              itemHeight: 50,
              scrollbarDecoration: ScrollbarDecoration(
                thickness: 12,
                radius: Radius.circular(6),
                trackColor: Colors.grey,
                trackBorderColor: Colors.red,
                thumbColor: Colors.orange,
              ),
              suggestionStyle: const TextStyle(fontSize: 18, color: Colors.black),
              suggestionItemDecoration: BoxDecoration(
                border: Border(
                  bottom: BorderSide(
                    color: Colors.grey.shade200,
                    width: 1,
                  ),
                ),
              ),
              searchInputDecoration: SearchInputDecoration(
                focusedBorder: OutlineInputBorder(
                  borderRadius: BorderRadius.circular(24),
                  borderSide: const BorderSide(
                    width: 1,
                    color: Colors.orange,
                    style: BorderStyle.solid,
                  ),
                ),
                border: OutlineInputBorder(
                  borderRadius: BorderRadius.circular(24),
                  borderSide: const BorderSide(
                    width: 1,
                    color: Colors.black,
                    style: BorderStyle.solid,
                  ),
                ),
                contentPadding: const EdgeInsets.symmetric(horizontal: 20),
              ),
              suggestionsDecoration: SuggestionDecoration(
                elevation: 8.0,
                selectionColor: Colors.grey.shade100,
                hoverColor: Colors.purple.shade100,
                gradient: LinearGradient(
                  colors: [
                    Color(0xfffc466b),
                    Color.fromARGB(255, 103, 128, 255)
                  ],
                  stops: [0.25, 0.75],
                  begin: Alignment.topLeft,
                  end: Alignment.bottomRight,
                ),
                borderRadius: BorderRadius.only(
                  bottomLeft: Radius.circular(10),
                  bottomRight: Radius.circular(10),
                ),
              ),
              suggestions: suggestions.map((e) => SearchFieldListItem<String>(e, child: searchChild(e))).toList(),
              suggestionState: Suggestion.expand,
              onSuggestionTap: (SearchFieldListItem<String> x) {
                setState(() {
                  selectedValue = x;
                });
              },
            ),
            SizedBox(height: 20),
            SearchField(
              hint: 'Basic SearchField',
              dynamicHeight: true,
              maxSuggestionBoxHeight: 300,
              onSuggestionTap: (SearchFieldListItem<String> item) {
                setState(() {
                  selectedValue = item;
                });
              },
              selectedValue: selectedValue,
              suggestions: suggestions.map(SearchFieldListItem<String>.new).toList(),
              suggestionState: Suggestion.expand,
            ),
          ],
        ),
      ),
    );
  }
}

关键属性说明

  • suggestions: 建议列表,必须提供。
  • onSearchTextChanged: 当搜索文本变化时的回调函数。
  • selectedValue: 当前选中的值。
  • validator: 输入验证函数。
  • onSubmit: 提交时的回调函数。
  • scrollbarDecoration: 滚动条样式。
  • suggestionsDecoration: 建议列表的装饰。
  • onSuggestionTap: 点击建议项时的回调函数。

通过这些属性,你可以轻松地创建一个功能丰富且美观的搜索框。希望这个例子能帮助你更好地理解和使用searchfield插件!


更多关于Flutter搜索功能插件searchfield的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter搜索功能插件searchfield的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何在Flutter应用中使用search_field插件来实现搜索功能的示例代码。请注意,search_field是一个第三方包,可能需要在你的pubspec.yaml文件中添加相应的依赖。

首先,确保在你的pubspec.yaml文件中添加search_field依赖:

dependencies:
  flutter:
    sdk: flutter
  search_field: ^latest_version  # 请替换为实际的最新版本号

然后运行flutter pub get来安装依赖。

接下来,你可以在你的Flutter应用中使用SearchField来实现搜索功能。以下是一个简单的示例,展示如何在一个列表视图中实现搜索:

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

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter SearchField Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final List<String> items = List.generate(100, (index) => "Item $index");
  String searchQuery = "";

  @override
  Widget build(BuildContext context) {
    final filteredItems = items.where((item) =>
        item.toLowerCase().contains(searchQuery.toLowerCase())).toList();

    return Scaffold(
      appBar: AppBar(
        title: Text('Search Demo'),
      ),
      body: Column(
        children: <Widget>[
          SearchField(
            controller: TextEditingController()
              ..addListener(() {
                setState(() {
                  searchQuery =
                      _textController.text; // 使用内部TextEditingController获取输入值
                });
              }),
            decoration: InputDecoration(
              prefixIcon: Icon(Icons.search),
              hintText: 'Search...',
              border: OutlineInputBorder(),
            ),
            onChanged: (value) {
              // 这里通常不需要手动更新searchQuery,因为我们在TextEditingController的监听器中已经处理了
              // setState(() {
              //   searchQuery = value;
              // });
            },
            style: TextStyle(fontSize: 18),
            // 你可以根据需要自定义更多属性
          ),
          Expanded(
            child: ListView.builder(
              itemCount: filteredItems.length,
              itemBuilder: (context, index) {
                return ListTile(
                  title: Text(filteredItems[index]),
                );
              },
            ),
          ),
        ],
      ),
    );
  }

  // 注意:SearchField内部已经使用了TextEditingController,但为了演示如何从外部获取值,
  // 这里我们定义了一个额外的_textController,但在实际使用中,你应该直接使用SearchField的controller属性
  // 或者通过SearchField的onChanged回调获取输入值。在这个例子中,我们通过监听SearchField的controller来更新searchQuery。
  // TextEditingController _textController = TextEditingController(); // 实际上不需要这行代码,仅用于说明
}

注意

  1. 在上面的代码中,我直接在SearchFieldcontroller属性中使用了一个TextEditingController,并添加了监听器来更新搜索查询。
  2. SearchFieldonChanged回调在这个例子中其实是不必要的,因为我们已经通过监听TextEditingController来处理输入变化。但在某些情况下,你可能想直接使用onChanged回调来处理搜索逻辑。
  3. 为了避免混淆,注释中提到的_textController实际上在代码示例中并未使用,仅用于说明如何从SearchField获取输入值。在实际代码中,你应该直接使用SearchFieldcontroller

这个示例展示了如何使用search_field插件来创建一个简单的搜索界面,并根据用户的输入动态过滤列表项。

回到顶部