Flutter智能搜索提示插件reactive_flutter_typeahead_plus的使用

Flutter智能搜索提示插件reactive_flutter_typeahead_plus的使用

reactive_flutter_typeahead_plus 是一个用于与 reactive_forms 结合使用的 Flutter 智能搜索提示插件。它基于 flutter_typeahead 包进行封装,提供了更方便的表单集成方式。

完整示例

以下是一个完整的示例代码,展示了如何在 Flutter 应用中使用 reactive_flutter_typeahead_plus 插件。

// ignore_for_file: depend_on_referenced_packages

import 'package:flutter/material.dart';
import 'package:reactive_flutter_typeahead_plus/reactive_flutter_typeahead_plus.dart';
import 'package:reactive_forms/reactive_forms.dart';

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

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

  // 构建表单
  FormGroup buildForm() => fb.group({
        'input': FormControl<String>(value: null),
        'input2': FormControl<String>(value: null),
      });

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: Scaffold(
        appBar: AppBar(),
        body: SafeArea(
          child: SingleChildScrollView(
            physics: const BouncingScrollPhysics(),
            padding: const EdgeInsets.symmetric(
              horizontal: 20.0,
              vertical: 20.0,
            ),
            child: ReactiveFormBuilder(
              form: buildForm,
              builder: (context, form, child) {
                return Column(
                  children: [
                    ReactiveTypeAhead<String, String>(
                      formControlName: 'input',
                      stringify: (_) => _,
                      textFieldConfiguration: TextFieldConfiguration(
                        autofocus: false,
                        style: DefaultTextStyle.of(context)
                            .style
                            .copyWith(fontStyle: FontStyle.italic),
                        decoration: const InputDecoration(
                          border: OutlineInputBorder(),
                        ),
                      ),
                      suggestionsCallback: (pattern) async {
                        return CitiesService.getSuggestions(pattern);
                      },
                      itemBuilder: (context, suggestion) {
                        return ListTile(
                          leading: const Icon(Icons.shopping_cart),
                          title: Text(suggestion),
                        );
                      },
                    ),
                    const SizedBox(height: 16),
                    ReactiveCupertinoTypeAhead<String, String>(
                      formControlName: 'input2',
                      stringify: (_) => _,
                      getImmediateSuggestions: true,
                      suggestionsCallback: (pattern) {
                        return Future.delayed(
                          const Duration(seconds: 1),
                          () => CitiesService.getSuggestions(pattern),
                        );
                      },
                      itemBuilder: (context, suggestion) {
                        return Material(
                          child: Padding(
                            padding: const EdgeInsets.all(4.0),
                            child: Text(
                              suggestion,
                            ),
                          ),
                        );
                      },
                    ),
                    ElevatedButton(
                      child: const Text('Sign Up'),
                      onPressed: () {
                        if (form.valid) {
                          // ignore: avoid_print
                          print(form.value);
                        } else {
                          form.markAllAsTouched();
                        }
                      },
                    ),
                  ],
                );
              },
            ),
          ),
        ),
      ),
    );
  }
}

class CitiesService {
  static final List<String> cities = [
    'Beirut',
    'Damascus',
    'San Fransisco',
    'Rome',
    'Los Angeles',
    'Madrid',
    'Bali',
    'Barcelona',
    'Paris',
    'Bucharest',
    'New York City',
    'Philadelphia',
    'Sydney',
  ];

  static List<String> getSuggestions(String query) {
    List<String> matches = [];
    matches.addAll(cities);

    matches.retainWhere((s) => s.toLowerCase().contains(query.toLowerCase()));
    return matches;
  }
}

代码解释

  1. 导入必要的包:

    import 'package:flutter/material.dart';
    import 'package:reactive_flutter_typeahead_plus/reactive_flutter_typeahead_plus.dart';
    import 'package:reactive_forms/reactive_forms.dart';
    
  2. 构建表单:

    FormGroup buildForm() => fb.group({
          'input': FormControl<String>(value: null),
          'input2': FormControl<String>(value: null),
        });
    

    这里定义了一个包含两个输入字段的表单。

  3. 主应用布局:

    [@override](/user/override)
    Widget build(BuildContext context) {
      return MaterialApp(
        theme: ThemeData(
          primarySwatch: Colors.blue,
          visualDensity: VisualDensity.adaptivePlatformDensity,
        ),
        home: Scaffold(
          appBar: AppBar(),
          body: SafeArea(
            child: SingleChildScrollView(
              physics: const BouncingScrollPhysics(),
              padding: const EdgeInsets.symmetric(
                horizontal: 20.0,
                vertical: 20.0,
              ),
              child: ReactiveFormBuilder(
                form: buildForm,
                builder: (context, form, child) {
                  return Column(
                    children: [
                      // 输入框1
                      ReactiveTypeAhead<String, String>(
                        formControlName: 'input',
                        ...
                      ),
                      const SizedBox(height: 16),
                      // 输入框2
                      ReactiveCupertinoTypeAhead<String, String>(
                        formControlName: 'input2',
                        ...
                      ),
                      ElevatedButton(
                        child: const Text('Sign Up'),
                        onPressed: () {
                          if (form.valid) {
                            // 忽略:避免打印
                            print(form.value);
                          } else {
                            form.markAllAsTouched();
                          }
                        },
                      ),
                    ],
                  );
                },
              ),
            ),
          ),
        ),
      );
    }
    
  4. 城市服务类:

    class CitiesService {
      static final List<String> cities = [
        'Beirut',
        'Damascus',
        'San Fransisco',
        'Rome',
        'Los Angeles',
        'Madrid',
        'Bali',
        'Barcelona',
        'Paris',
        'Bucharest',
        'New York City',
        'Philadelphia',
        'Sydney',
      ];
    
      static List<String> getSuggestions(String query) {
        List<String> matches = [];
        matches.addAll(cities);
    
        matches.retainWhere((s) => s.toLowerCase().contains(query.toLowerCase()));
        return matches;
      }
    }
    

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

1 回复

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


reactive_flutter_typeahead_plus 是一个 Flutter 插件,用于实现带有智能搜索提示的输入框。它基于 flutter_typeahead 插件,并且与 reactive_forms 插件集成,使得它可以轻松地与表单管理相结合。

安装

首先,你需要在 pubspec.yaml 文件中添加依赖:

dependencies:
  reactive_flutter_typeahead_plus: ^0.0.1

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

基本用法

以下是一个简单的例子,展示了如何使用 reactive_flutter_typeahead_plus 插件:

import 'package:flutter/material.dart';
import 'package:reactive_forms/reactive_forms.dart';
import 'package:reactive_flutter_typeahead_plus/reactive_flutter_typeahead_plus.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Reactive Flutter Typeahead Plus Example'),
        ),
        body: MyForm(),
      ),
    );
  }
}

class MyForm extends StatelessWidget {
  final form = FormGroup({
    'city': FormControl<String>(),
  });

  @override
  Widget build(BuildContext context) {
    return ReactiveForm(
      formGroup: form,
      child: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: [
            ReactiveFlutterTypeAheadPlus<String, String>(
              formControlName: 'city',
              suggestionsCallback: (pattern) async {
                // 这里可以是从 API 或其他数据源获取建议的逻辑
                return ['New York', 'Los Angeles', 'Chicago', 'Houston']
                    .where((city) => city.toLowerCase().contains(pattern.toLowerCase()))
                    .toList();
              },
              itemBuilder: (context, suggestion) {
                return ListTile(
                  title: Text(suggestion),
                );
              },
              onSuggestionSelected: (suggestion) {
                form.control('city').value = suggestion;
              },
              decoration: InputDecoration(
                labelText: 'City',
                hintText: 'Enter a city name',
              ),
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: () {
                if (form.valid) {
                  print(form.value);
                }
              },
              child: Text('Submit'),
            ),
          ],
        ),
      ),
    );
  }
}

参数说明

  • formControlName: 与 reactive_forms 集成的字段名,用于管理表单状态。
  • suggestionsCallback: 一个异步回调函数,用于根据用户输入提供建议列表。
  • itemBuilder: 用于构建每个建议项的 Widget。
  • onSuggestionSelected: 当用户选择一个建议项时触发的回调。
  • decoration: 输入框的装饰属性,如标签、提示文本等。

高级用法

你可以根据需要进一步自定义 ReactiveFlutterTypeAheadPlus 的行为,例如设置延迟时间、最小输入字符数等。

ReactiveFlutterTypeAheadPlus<String, String>(
  formControlName: 'city',
  suggestionsCallback: (pattern) async {
    // 模拟从 API 获取数据
    return ['New York', 'Los Angeles', 'Chicago', 'Houston']
        .where((city) => city.toLowerCase().contains(pattern.toLowerCase()))
        .toList();
  },
  itemBuilder: (context, suggestion) {
    return ListTile(
      title: Text(suggestion),
    );
  },
  onSuggestionSelected: (suggestion) {
    form.control('city').value = suggestion;
  },
  decoration: InputDecoration(
    labelText: 'City',
    hintText: 'Enter a city name',
  ),
  debounceDuration: Duration(milliseconds: 300), // 设置延迟时间
  minCharsForSuggestions: 2, // 最小输入字符数
);
回到顶部