Flutter动态搜索栏插件dynamic_searchbar的使用

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

Flutter 动态搜索栏插件 dynamic_searchbar 的使用

简介

定义您的字段,并通过关键字、日期范围和数字范围过滤列表。还可以对其进行排序。您可以在前端和后端进行过滤。

使用方法

首先,定义您的过滤器,如下所示:

final List<FilterAction> employeeFilter = [
  FilterAction(
    title: 'Firstname',
    field: 'firstname',
  ),
  FilterAction(
    title: 'Age',
    field: 'age',
    type: FilterType.numberRangeFilter,
    numberRange: const RangeValues(18, 65),
  ),
  FilterAction(
    title: 'Hired date',
    field: 'hiredDate',
    type: FilterType.dateRangeFilter,
    dateRange: DateTimeRange(
      start: DateTime.now(),
      end: DateTime.now(),
    ),
  ),
];

final List<SortAction> employeeSort = [
  SortAction(
    title: 'Firstname ASC',
    field: 'firstname',
  ),
  SortAction(
    title: 'Email DESC',
    field: 'email',
    order: OrderType.desc,
  ),
  SortAction(
    title: 'Hired date ASC',
    field: 'hiredDate',
  ),
];

然后使用 SearchField 组件:

SearchField(
  disableFilter: false, // 如果为 true,则禁用过滤器。
  filters: employeeFilter, // 指定您的过滤器
  sorts: employeeSort, // 指定您的排序
  initialData: sampleList, // 指定要过滤的数据
  onChanged: (List<Employee> data) => setState(
    () => samples = data,
  ), // 过滤时返回的值将在 onChanged 方法中返回。
  onFilter: (Map filters) => print(filters), // 过滤后的 JSON 数据将返回。
),

自定义过滤器

如果您想自定义过滤器,可以将其包装在 GlobalSearchbar 组件中。然后需要定义 SearchThemeData 对象。以下是一个示例代码:

SearchThemeData(
  filterIcon: Icons.filter_list_sharp,
  title: 'Filter',
  filterTitle: 'Filters',
  sortTitle: 'Sorts',
  primaryColor: Colors.tealAccent,
  iconColor: const Color(0xFFE8E7E4),
  applyButton: ActionButtonTheme(
    title: 'Apply',
    style: ButtonStyle(
      backgroundColor: MaterialStateProperty.all<Color>(const Color(0xFF348FFF)),
    ),
  ),
  clearFilterButton: ActionButtonTheme(
    title: 'Clear filter',
    style: ButtonStyle(
      backgroundColor: MaterialStateProperty.all<Color>(const Color(0xFF3DD89B)),
    ),
  ),
  cancelButton: ActionButtonTheme(
    title: 'Cancel',
    style: ButtonStyle(
      backgroundColor: MaterialStateProperty.all<Color>(const Color(0xFFE8E7E4)),
    ),
  ),
);

示例

完整示例代码

import 'package:dynamic_searchbar/dynamic_searchbar.dart';
import 'package:faker/faker.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';

class Employee {
  final int id;
  final String lastname;
  final String firstname;
  final String email;
  final String position;
  final int age;
  final String hiredDate;

  Employee({
    required this.id,
    required this.lastname,
    required this.firstname,
    required this.email,
    required this.position,
    required this.age,
    required this.hiredDate,
  });

  Employee.fromJson(Map<String, dynamic> json)
      : id = json['id'],
        lastname = json['lastname'],
        firstname = json['firstname'],
        email = json['email'],
        position = json['position'],
        age = json['age'],
        hiredDate = json['hiredDate'];

  Map<String, dynamic> toJson() {
    return {
      'id': id,
      'lastname': lastname,
      'firstname': firstname,
      'email': email,
      'position': position,
      'age': age,
      'hiredDate': hiredDate
    };
  }
}

class NoThumbScrollBehavior extends ScrollBehavior {
  [@override](/user/override)
  Set<PointerDeviceKind> get dragDevices => {
        PointerDeviceKind.touch,
        PointerDeviceKind.mouse,
        PointerDeviceKind.stylus,
      };
}

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

class TestingApp extends StatelessWidget {
  const TestingApp({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) {
    return GlobalSearchbar(
      searchThemeData: SearchThemeData(
        filterIcon: Icons.filter_list_sharp,
        title: 'Filter',
        filterTitle: 'Filters',
        sortTitle: 'Sorts',
        primaryColor: Colors.tealAccent,
        iconColor: const Color(0xFFE8E7E4),
        applyButton: ActionButtonTheme(
          title: 'Apply',
          style: ButtonStyle(
            backgroundColor: MaterialStateProperty.all<Color>(const Color(0xFF348FFF)),
          ),
        ),
        clearFilterButton: ActionButtonTheme(
          title: 'Clear filter',
          style: ButtonStyle(
            backgroundColor: MaterialStateProperty.all<Color>(const Color(0xFF3DD89B)),
          ),
        ),
        cancelButton: ActionButtonTheme(
          title: 'Cancel',
          style: ButtonStyle(
            backgroundColor: MaterialStateProperty.all<Color>(const Color(0xFFE8E7E4)),
          ),
        ),
      ),
      child: MaterialApp(
        title: 'Testing Sample',
        debugShowCheckedModeBanner: false,
        scrollBehavior: NoThumbScrollBehavior().copyWith(scrollbars: false),
        theme: ThemeData(),
        routes: {
          HomePage.routeName: (context) => const HomePage(),
        },
        initialRoute: HomePage.routeName,
      ),
    );
  }
}

class HomePage extends StatefulWidget {
  static const routeName = '/';

  const HomePage({super.key});

  [@override](/user/override)
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  final List<FilterAction> employeeFilter = [
    FilterAction(
      title: 'Firstname',
      field: 'firstname',
    ),
    FilterAction(
      title: 'Lastname',
      field: 'lastname',
    ),
    FilterAction(
      title: 'Age',
      field: 'age',
      type: FilterType.numberRangeFilter,
      numberRange: const RangeValues(18, 65),
      maxNumberRange: 65,
      minNumberRange: 18,
    ),
    FilterAction(
      title: 'Hired date',
      field: 'hiredDate',
      type: FilterType.dateRangeFilter,
      dateRange: DateTimeRange(
        start: DateTime.now(),
        end: DateTime.now(),
      ),
    ),
  ];

  final List<SortAction> employeeSort = [
    SortAction(
      title: 'Firstname ASC',
      field: 'firstname',
    ),
    SortAction(
      title: 'Lastname ASC',
      field: 'lastname',
    ),
    SortAction(
      title: 'Email DESC',
      field: 'email',
      order: OrderType.desc,
    ),
    SortAction(
      title: 'Position DESC',
      field: 'position',
      order: OrderType.desc,
    ),
    SortAction(
      title: 'Hired date ASC',
      field: 'hiredDate',
    ),
    SortAction(
      title: 'Hired date DESC',
      field: 'hiredDate',
      order: OrderType.desc,
    ),
  ];

  final sampleList = List<Employee>.generate(
    100,
    (index) => Employee(
      id: index,
      firstname: Faker().person.firstName(),
      lastname: Faker().person.lastName(),
      position: Faker().job.title(),
      email: Faker().internet.email(),
      age: Faker().randomGenerator.integer(65, min: 18),
      hiredDate: Faker().date.dateTime(minYear: 1990, maxYear: 2022).toString(),
    ),
  );

  List samples = [];

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Testing Sample'),
      ),
      body: Padding(
        padding: const EdgeInsets.symmetric(horizontal: 16.0),
        child: Column(
          children: [
            const SizedBox(height: 16.0),
            SearchField(
              filters: employeeFilter,
              sorts: employeeSort,
              initialData: sampleList,
              onChanged: (List<Employee> data) => setState(
                () => samples = data,
              ),
              onFilter: (Map filters) => print(filters),
            ),
            Expanded(
              flex: 10,
              child: ListView.builder(
                  itemCount: samples.length,
                  itemBuilder: ((context, index) {
                    final employee = samples[index];

                    return Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Row(
                        children: [
                          Expanded(
                            flex: 1,
                            child: Column(
                              crossAxisAlignment: CrossAxisAlignment.start,
                              children: [
                                const Text('id'),
                                Text(
                                  employee.id.toString(),
                                )
                              ],
                            ),
                          ),
                          Expanded(
                            flex: 2,
                            child: Column(
                              crossAxisAlignment: CrossAxisAlignment.start,
                              children: [
                                const Text('Firstname'),
                                Text(
                                  employee.firstname,
                                )
                              ],
                            ),
                          ),
                          Expanded(
                            flex: 2,
                            child: Column(
                              crossAxisAlignment: CrossAxisAlignment.start,
                              children: [
                                const Text('Lastname'),
                                Text(
                                  employee.lastname,
                                )
                              ],
                            ),
                          ),
                          Expanded(
                            flex: 2,
                            child: Column(
                              crossAxisAlignment: CrossAxisAlignment.start,
                              children: [
                                const Text('Email'),
                                Text(
                                  employee.email,
                                )
                              ],
                            ),
                          ),
                          Expanded(
                            flex: 2,
                            child: Column(
                              crossAxisAlignment: CrossAxisAlignment.start,
                              children: [
                                const Text('Position'),
                                Text(
                                  employee.position,
                                )
                              ],
                            ),
                          ),
                          Expanded(
                            flex: 2,
                            child: Column(
                              crossAxisAlignment: CrossAxisAlignment.start,
                              children: [
                                const Text('Age'),
                                Text(
                                  employee.age.toString(),
                                )
                              ],
                            ),
                          ),
                          Expanded(
                            flex: 2,
                            child: Column(
                              crossAxisAlignment: CrossAxisAlignment.start,
                              children: [
                                const Text('Hired date'),
                                Text(
                                  employee.hiredDate.toString(),
                                )
                              ],
                            ),
                          ),
                        ],
                      ),
                    );
                  })),
            ),
          ],
        ),
      ),
    );
  }
}

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

1 回复

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


当然,以下是一个关于如何在Flutter项目中使用dynamic_searchbar插件的示例代码。dynamic_searchbar插件允许你创建一个具有动态搜索功能的搜索栏。以下是一个简单的示例,展示了如何设置和使用该插件。

首先,确保你已经在pubspec.yaml文件中添加了dynamic_searchbar依赖:

dependencies:
  flutter:
    sdk: flutter
  dynamic_searchbar: ^x.y.z  # 请替换为最新版本号

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

接下来,是一个完整的示例代码,展示如何使用dynamic_searchbar插件:

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Dynamic Searchbar 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) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Dynamic Searchbar Demo'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(8.0),
        child: Column(
          children: [
            Expanded(
              child: DynamicSearchBar<String>(
                data: items,
                onItemFound: (item, index) {
                  // 当用户选择一个项目时触发
                  print('Selected item: $item');
                },
                onSearch: (query) {
                  // 更新搜索查询
                  setState(() {
                    searchQuery = query;
                  });
                },
                searchBarDecoration: InputDecoration(
                  border: OutlineInputBorder(),
                  labelText: 'Search...',
                  hintText: 'Search for items',
                ),
                emptyResultWidget: Center(
                  child: Text('No results found for "$searchQuery"'),
                ),
                itemBuilder: (context, item, index) {
                  return ListTile(
                    title: Text(item),
                  );
                },
              ),
            ),
          ],
        ),
      ),
    );
  }
}

代码解释:

  1. 依赖导入

    • 导入flutter/material.dart用于基本的Material Design组件。
    • 导入dynamic_searchbar/dynamic_searchbar.dart以使用DynamicSearchBar组件。
  2. 主应用

    • MyApp类作为应用的入口,设置了基本的Material应用主题。
  3. 主页面

    • MyHomePage是一个有状态的组件,用于管理搜索栏的状态。
    • 定义一个包含100个字符串项的列表items
    • searchQuery字符串用于存储当前的搜索查询。
  4. 搜索栏

    • DynamicSearchBar组件用于创建搜索栏。
    • data属性传递要搜索的项列表。
    • onItemFound回调用于处理用户选择某个项时的逻辑。
    • onSearch回调用于处理搜索查询的变化,并更新状态。
    • searchBarDecoration用于自定义搜索栏的样式。
    • emptyResultWidget用于在搜索结果为空时显示自定义的占位符。
    • itemBuilder用于构建搜索结果的每一项。

这个示例展示了如何使用dynamic_searchbar插件创建一个基本的搜索功能。你可以根据需求进一步自定义和扩展这个示例。

回到顶部