Flutter标签输入插件chips_input的使用

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

Flutter标签输入插件chips_input的使用

chips_input 是一个用于构建具有输入选项的输入字段的 Flutter 库。它允许用户通过选择标签或输入文本来添加数据。

版本信息

  • Pub版本: Pub Version
  • GitHub工作流状态: GitHub Workflow Status

使用方法

导入

首先,需要导入 chips_input 包:

import 'package:chips_input/chips_input.dart';
示例

以下是一个完整的示例,展示了如何使用 chips_input 插件:

  1. 首先创建一个类来存储数据。这里我们使用了一个简单的 AppProfile 类:
class AppProfile {
  final String name;
  final String email;
  final String imageUrl;

  const AppProfile(this.name, this.email, this.imageUrl);

  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is AppProfile &&
          runtimeType == other.runtimeType &&
          name == other.name;

  @override
  int get hashCode => name.hashCode;

  @override
  String toString() {
    return name;
  }
}
  1. 初始化一些数据并实现 ChipsInput 组件:
const mockResults = [
    AppProfile('John Doe', 'jdoe@flutter.io',
        'https://d2gg9evh47fn9z.cloudfront.net/800px_COLOURBOX4057996.jpg'),
    AppProfile('Paul', 'paul@google.com',
        'https://upload.wikimedia.org/wikipedia/commons/7/7c/Profile_avatar_placeholder_large.png'),
    AppProfile('Fred', 'fred@google.com',
        'https://upload.wikimedia.org/wikipedia/commons/7/7c/Profile_avatar_placeholder_large.png'),
    AppProfile('Brian', 'brian@flutter.io',
        'https://upload.wikimedia.org/wikipedia/commons/7/7c/Profile_avatar_placeholder_large.png'),
    AppProfile('John', 'john@flutter.io',
        'https://upload.wikimedia.org/wikipedia/commons/7/7c/Profile_avatar_placeholder_large.png'),
    AppProfile('Thomas', 'thomas@flutter.io',
        'https://upload.wikimedia.org/wikipedia/commons/7/7c/Profile_avatar_placeholder_large.png'),
    AppProfile('Nelly', 'nelly@flutter.io',
        'https://upload.wikimedia.org/wikipedia/commons/7/7c/Profile_avatar_placeholder_large.png'),
    AppProfile('Marie', 'marie@flutter.io',
        'https://upload.wikimedia.org/wikipedia/commons/7/7c/Profile_avatar_placeholder_large.png'),
    AppProfile('Charlie', 'charlie@flutter.io',
        'https://upload.wikimedia.org/wikipedia/commons/7/7c/Profile_avatar_placeholder_large.png'),
    AppProfile('Diana', 'diana@flutter.io',
        'https://upload.wikimedia.org/wikipedia/commons/7/7c/Profile_avatar_placeholder_large.png'),
    AppProfile('Ernie', 'ernie@flutter.io',
        'https://upload.wikimedia.org/wikipedia/commons/7/7c/Profile_avatar_placeholder_large.png'),
    AppProfile('Gina', 'fred@flutter.io',
        'https://upload.wikimedia.org/wikipedia/commons/7/7c/Profile_avatar_placeholder_large.png'),
];

// 实现ChipsInput组件
ChipsInput(
  maxChips: 3, // 最多可以输入3个标签
  initialValue: [mockResults[1]], // 初始值为mockResults的第一个元素
  findSuggestions: (String query) {
    if (query.isNotEmpty) {
      var lowercaseQuery = query.toLowerCase();
      final results = mockResults.where((profile) {
        return profile.name
                .toLowerCase()
                .contains(query.toLowerCase()) ||
            profile.email
                .toLowerCase()
                .contains(query.toLowerCase());
      }).toList(growable: false)
        ..sort((a, b) => a.name
            .toLowerCase()
            .indexOf(lowercaseQuery)
            .compareTo(
                b.name.toLowerCase().indexOf(lowercaseQuery)));
      return results;
    }
    return mockResults;
  },
  onChanged: (data) {
    print(data); // 打印选中的标签
  },
  chipBuilder: (context, state, AppProfile profile) {
    return InputChip(
      key: ObjectKey(profile),
      label: Text(profile.name),
      avatar: CircleAvatar(
        backgroundImage: NetworkImage(profile.imageUrl),
      ),
      onDeleted: () => state.deleteChip(profile),
      materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
    );
  },
  suggestionBuilder: (context, AppProfile profile) {
    return ListTile(
      key: ObjectKey(profile),
      leading: CircleAvatar(
        backgroundImage: NetworkImage(profile.imageUrl),
      ),
      title: Text(profile.name),
      subtitle: Text(profile.email),
    );
  },
)
自定义选项视图

除了使用 suggestionBuilder,你还可以传递 optionsViewBuilder 来进行更多自定义:

optionsViewBuilder: (context, onSelected, options) {
  return Align(
    alignment: Alignment.topLeft,
    child: Material(
      elevation: 4.0,
      child: Container(
        height: 200.0,
        child: ListView.builder(
          padding: EdgeInsets.all(8.0),
          itemCount: options.length,
          itemBuilder: (BuildContext context, int index) {
            final option = options.elementAt(index);
            return GestureDetector(
              onTap: () {
                onSelected(option);
              },
              child: ListTile(
                key: ObjectKey(option),
                leading: CircleAvatar(
                  backgroundImage: NetworkImage(option.imageUrl),
                ),
                title: Text(option.name),
                subtitle: Text(option.email),
              ),
            );
          },
        ),
      ),
    ),
  );
},

更多关于Flutter标签输入插件chips_input的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter标签输入插件chips_input的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter应用中使用chips_input插件来实现标签输入功能的示例代码。chips_input插件允许用户输入和选择多个标签,非常适合在表单或聊天应用中使用。

首先,确保你的pubspec.yaml文件中包含了chips_input依赖项:

dependencies:
  flutter:
    sdk: flutter
  chips_input: ^3.0.1  # 请根据需要检查最新版本号

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

接下来,在你的Dart文件中使用ChipsInput组件。以下是一个完整的示例,展示了如何设置和使用chips_input插件:

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

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

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

class ChipsInputScreen extends StatefulWidget {
  @override
  _ChipsInputScreenState createState() => _ChipsInputScreenState();
}

class _ChipsInputScreenState extends State<ChipsInputScreen> {
  final TextEditingController _controller = TextEditingController();
  List<String> _chips = [];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Chips Input Demo'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            ChipsInput<String>(
              initialValue: _chips.toSet(),
              onChanged: (chips) {
                setState(() {
                  _chips = chips.toList();
                });
              },
              findSuggestions: (String query) {
                // 模拟从服务器获取建议标签
                if (query.isEmpty) return [];
                return List.generate(10, (i) => '${query} Item $i');
              },
              chipBuilder: (context, state, chip) {
                return InputChip(
                  label: Text(chip),
                  onDeleted: () => state.deleteChip(chip),
                  materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
                );
              },
              suggestionBuilder: (context, state, suggestion) {
                return ListTile(
                  leading: Icon(Icons.add),
                  title: Text(suggestion),
                  onTap: () => state.selectSuggestion(suggestion),
                );
              },
              decorator: InputDecorator(
                decoration: InputDecoration(
                  prefixIcon: Icon(Icons.label),
                  border: OutlineInputBorder(),
                  labelText: 'Enter chips',
                ),
                isEmpty: _controller.text.isEmpty,
                child: TextField(
                  controller: _controller,
                  onSubmitted: (value) {
                    if (value.isNotEmpty && !_chips.contains(value)) {
                      setState(() {
                        _chips.add(value);
                      });
                      _controller.clear();
                    }
                  },
                ),
              ),
            ),
            SizedBox(height: 16),
            Text('Selected Chips: $_chips'),
          ],
        ),
      ),
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
}

解释

  1. 依赖导入:在pubspec.yaml中添加chips_input依赖项。
  2. UI结构:使用ScaffoldAppBarColumn来构建UI结构。
  3. ChipsInput组件
    • initialValue:初始标签集合。
    • onChanged:当标签集合更改时触发。
    • findSuggestions:根据用户输入查询建议标签。
    • chipBuilder:自定义芯片(Chip)的外观。
    • suggestionBuilder:自定义建议项的外观。
    • decorator:包装TextField,并自定义其装饰。
  4. TextField:用于输入新标签,当输入提交时(按下回车键),如果输入不为空且不在当前标签集合中,则将其添加到集合中。
  5. 清理:在dispose方法中释放TextEditingController资源。

这个示例展示了如何使用chips_input插件来实现一个功能完备的标签输入界面。你可以根据需要进一步自定义和扩展这个示例。

回到顶部