Flutter聊天提及控制插件v_chat_mention_controller的使用

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

Flutter聊天提及控制插件v_chat_mention_controller的使用

v_chat_mention_controller 是一个用于在Flutter应用中实现聊天提及(mention)功能的插件。它可以帮助开发者轻松地检测文本字段中的提及符号(如 @),并支持多种语言和自定义小部件。本文将详细介绍如何使用该插件,并提供一个完整的示例demo。

主要特性

  • 检测提及:自动检测文本字段中的提及符号(默认为 @
  • 多语言支持:支持所有语言
  • 自定义小部件:可以自定义提及项的显示样式和交互逻辑
  • 控制器管理:通过创建控制器来管理提及逻辑,确保在屏幕退出时调用 dispose 方法释放资源
  • 搜索监听:可以通过 onSearch 监听器响应提及搜索事件

示例代码

下面是一个完整的示例demo,展示了如何在Flutter应用中使用 v_chat_mention_controller 插件:

import 'package:flutter/material.dart';
import 'package:flutter_parsed_text/flutter_parsed_text.dart';
import 'package:v_chat_mention_controller/v_chat_mention_controller.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, this.title}) : super(key: key);

  final String? title;

  @override
  MyHomePageState createState() => MyHomePageState();
}

class MyHomePageState extends State<MyHomePage> {
  final controller = VChatTextMentionController(
    debounce: 500,
    mentionStyle: const TextStyle(
      color: Colors.deepPurple,
      fontWeight: FontWeight.w800,
    ),
  );

  String parsedText = "";
  final logs = <String>[];
  final _fakeUsersDataServer = List.generate(100, (index) => "user $index");
  final users = <String>[];
  bool _isSearchCanView = false;

  @override
  void initState() {
    super.initState();
    controller.onSearch = (str) async {
      users.clear();
      if (str != null) {
        _isSearchCanView = true;
        if (str.isEmpty) {
          users.addAll(_fakeUsersDataServer);
        }
        for (var element in _fakeUsersDataServer) {
          if (element.startsWith(str)) {
            users.add(element);
          }
        }
      } else {
        _isSearchCanView = false;
      }
      setState(() {});
    };
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title!),
      ),
      body: Padding(
        padding: const EdgeInsets.all(8.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Expanded(
              child: ListView.builder(
                itemBuilder: (context, index) => ListTile(
                  title: ParsedText(
                    text: logs[index],
                    style: const TextStyle(color: Colors.black87),
                    parse: [
                      MatchText(
                        pattern: r"\[(@[^:]+):([^\]]+)\]",
                        style: const TextStyle(color: Colors.indigo),
                        renderWidget: ({required pattern, required text}) {
                          return Text(text);
                        },
                        renderText: (
                            {required String str, required String pattern}) {
                          final map = <String, String>{};
                          final RegExp customRegExp =
                              RegExp(r"\[(@[^:]+):([^\]]+)\]");
                          final match = customRegExp.firstMatch(str);
                          map['display'] = match!.group(1)!;
                          return map;
                        },
                        onTap: (url) {
                          final customRegExp = RegExp(r"\[(@[^:]+):([^\]]+)\]");
                          final match = customRegExp.firstMatch(url)!;
                          final snackBar = SnackBar(
                            content: Text(
                                'id is ${match.group(2)} name is ${match.group(1)}'),
                            duration: const Duration(seconds: 7),
                          );

                          ScaffoldMessenger.of(context).showSnackBar(snackBar);
                        },
                      ),
                    ],
                  ),
                ),
                itemCount: logs.length,
              ),
            ),
            Column(
              children: [
                Visibility(
                  visible: _isSearchCanView,
                  child: SizedBox(
                    height: 200,
                    child: ListView(
                      shrinkWrap: true,
                      children: users
                          .map(
                            (e) => ListTile(
                              onTap: () {
                                controller.addMention(
                                  MentionData(
                                    id: "id-$e",
                                    display: e,
                                  ),
                                );
                              },
                              title: Text(e),
                            ),
                          )
                          .toList(),
                    ),
                  ),
                ),
                Row(
                  children: [
                    Expanded(
                      child: TextField(
                        controller: controller,
                      ),
                    ),
                    FloatingActionButton(
                      onPressed: () {
                        setState(() {
                          logs.add(controller.markupText);
                          controller.clear();
                        });
                      },
                      child: const Text("Send"),
                    )
                  ],
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

关键点解释

  1. 控制器初始化

    • 创建 VChatTextMentionController 实例,并设置延迟时间(debounce)和提及样式的自定义样式。
    final controller = VChatTextMentionController(
      debounce: 500,
      mentionStyle: const TextStyle(
        color: Colors.deepPurple,
        fontWeight: FontWeight.w800,
      ),
    );
    
  2. 搜索监听

    • 设置 onSearch 监听器,当用户输入提及符号后,根据输入内容过滤用户列表并更新UI。
    controller.onSearch = (str) async {
      users.clear();
      if (str != null) {
        _isSearchCanView = true;
        if (str.isEmpty) {
          users.addAll(_fakeUsersDataServer);
        }
        for (var element in _fakeUsersDataServer) {
          if (element.startsWith(str)) {
            users.add(element);
          }
        }
      } else {
        _isSearchCanView = false;
      }
      setState(() {});
    };
    
  3. 添加提及

    • 使用 controller.addMention 方法添加提及项。
    controller.addMention(
      MentionData(
        id: "id-$e",
        display: e,
      ),
    );
    
  4. 获取标记文本

    • 使用 controller.markupText 获取包含提及信息的标记文本。
    logs.add(controller.markupText);
    
  5. 解析和显示提及文本

    • 使用 flutter_parsed_text 包解析并显示提及文本,支持点击提及项触发特定操作。
    ParsedText(
      text: logs[index],
      style: const TextStyle(color: Colors.black87),
      parse: [
        MatchText(
          pattern: r"\[(@[^:]+):([^\]]+)\]",
          style: const TextStyle(color: Colors.indigo),
          renderWidget: ({required pattern, required text}) {
            return Text(text);
          },
          renderText: (
              {required String str, required String pattern}) {
            final map = <String, String>{};
            final RegExp customRegExp =
                RegExp(r"\[(@[^:]+):([^\]]+)\]");
            final match = customRegExp.firstMatch(str);
            map['display'] = match!.group(1)!;
            return map;
          },
          onTap: (url) {
            final customRegExp = RegExp(r"\[(@[^:]+):([^\]]+)\]");
            final match = customRegExp.firstMatch(url)!;
            final snackBar = SnackBar(
              content: Text(
                  'id is ${match.group(2)} name is ${match.group(1)}'),
              duration: const Duration(seconds: 7),
            );
    
            ScaffoldMessenger.of(context).showSnackBar(snackBar);
          },
        ),
      ],
    ),
    

通过以上步骤,你可以在Flutter应用中实现一个完整的聊天提及功能。希望这个示例对你有所帮助!如果有任何问题或需要进一步的帮助,请随时提问。


更多关于Flutter聊天提及控制插件v_chat_mention_controller的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter聊天提及控制插件v_chat_mention_controller的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是关于如何在Flutter项目中使用v_chat_mention_controller插件的一个简单示例代码。这个插件通常用于在聊天应用中实现提及(@提及用户)功能。需要注意的是,具体的实现可能会根据插件的版本和API有所变化,以下示例假设你已经正确地在pubspec.yaml文件中添加了v_chat_mention_controller依赖,并且已经运行了flutter pub get

首先,确保你的pubspec.yaml文件中包含以下依赖:

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

然后,在你的Flutter项目中,你可以按照以下步骤使用v_chat_mention_controller插件:

  1. 导入插件

在你的Dart文件中导入插件:

import 'package:v_chat_mention_controller/v_chat_mention_controller.dart';
  1. 初始化控制器

创建一个VChatMentionController实例,并配置提及用户列表:

class ChatScreen extends StatefulWidget {
  @override
  _ChatScreenState createState() => _ChatScreenState();
}

class _ChatScreenState extends State<ChatScreen> {
  late VChatMentionController _mentionController;
  List<String> _users = ['alice', 'bob', 'charlie']; // 示例用户列表

  @override
  void initState() {
    super.initState();
    _mentionController = VChatMentionController(
      users: _users,
      onMentionSelected: (String user) {
        // 用户被提及时的回调
        print('User $user was mentioned');
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Chat Screen'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(8.0),
        child: TextField(
          controller: _mentionController.textEditingController,
          decoration: InputDecoration(
            border: OutlineInputBorder(),
            hintText: 'Type a message...',
            suffixIcon: IconButton(
              icon: Icon(Icons.attach_file),
              onPressed: () {},
            ),
          ),
          // 自定义文本输入格式化器,用于处理提及
          inputFormatters: [
            FilteringTextInputFormatter.allow(RegExp(r'^[a-zA-Z0-9@ ]*$')), // 允许字母、数字和空格
            _mentionController.mentionTextFormatter, // 添加提及格式化器
          ],
        ),
      ),
    );
  }

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

在这个示例中,我们做了以下几件事:

  • 导入v_chat_mention_controller包。
  • 创建一个用户列表_users,其中包含可以被提及的用户名。
  • 初始化VChatMentionController,并传入用户列表和一个当用户被提及时的回调函数。
  • TextField中使用_mentionController.textEditingController作为控制器,并添加_mentionController.mentionTextFormatter作为输入格式化器,以处理提及逻辑。

这个示例展示了如何使用v_chat_mention_controller插件来实现基本的提及功能。你可以根据实际需求进一步自定义和扩展这个示例,比如处理不同的用户数据、调整UI样式等。

请注意,由于插件的API可能会随着版本更新而变化,因此在实际使用中,请参考插件的官方文档以获取最新的使用指南和API参考。

回到顶部