Flutter文本提及插件ruki_flutter_mentions的使用

Flutter文本提及插件ruki_flutter_mentions的使用

📛 Flutter Mentions

一个简单的 Flutter 输入小部件,为您的应用程序添加 @ 提及功能

安装 📦

要使用此软件包,请在 pubspec.yaml 文件中将 flutter_mentions 添加为依赖项。

dependencies:
  flutter:
    sdk: flutter
  ruki_flutter_mentions:

然后,在终端中运行 flutter packages get

使用 💻

要使用此软件包,您必须首先用 Portal 包裹您的顶级小部件,因为此软件包使用 flutter_portal 来显示建议列表。

Portal(
  child: MaterialApp(
    ...
  )
);

(适用于 CupertinoApp

这样,Portal 将渲染在所有内容之上。但是,您可以将其放置在其他位置以更改剪辑行为。

小部件

FlutterMention

  • mentions: List<Mention> - 允许用户触发的提及列表。
  • suggestionPosition: SuggestionPosition - 建议模态框的位置,可以对齐到 [Top][Bottom]
  • onMentionAdd: Function(Map<String, dynamic>) - 当用户点击建议时触发。
  • suggestionListHeight: double - 建议列表的最大高度,默认为 300.0。
  • onMarkupChanged: Function(String) - 每次输入变化时触发的函数,并带有选中提及的标记。
  • suggestionListDecoration: BoxDecoration - 建议列表的装饰。
  • defaultText: String - 预填充输入字段的文本。
  • onSearchChange: Function(String trigger, String value) - 当用户搜索提及项目时触发。
  • leading: List<Widget> - 放置在输入之前的组件列表。
  • trailing: List<Widget> - 放置在输入之后的组件列表。
  • onSuggestionVisibleChanged: Function(bool) - 当建议列表可见性改变时触发。
  • 支持 TextField 的所有其他属性。

Mention

  • trigger: String - 用于触发建议的单个字符。
  • data: List<Map<String, dynamic>> - 显示给用户的建议列表。需要提供两个必需属性 iddisplay,两者都是 [String]。您还可以根据需要添加自定义属性以构建自定义建议组件(注意:这可以稍后更新以显示新的或过滤后的提及列表)。
  • style: TextStyle - 输入中的提及项目的样式。
  • matchAll: bool - 是否应匹配带有触发字符的所有非建议。
  • disableMarkup: bool - 是否应禁用此提及项目的标记生成。
  • suggestionBuilder: Widget Function(Map<String, dynamic>) - 使用此生成器构建自定义建议组件。
  • markupBuilder: String Function(String trigger, String mention, String value) - 用于定义如何保存提及的标记。

示例

Mention(
  trigger: "#",
  disableMarkup: true,
  style: TextStyle(
    color: Colors.blue,
  ),
  data: [
    {"id": "reactjs", "display": "reactjs"},
    {"id": "javascript", "display": "javascript"},
  ],
  matchAll: true,
)

示例

import 'dart:convert';
import 'dart:math';

import 'package:flutter/material.dart';
import 'package:ruki_flutter_mentions/ruki_flutter_mentions.dart';
import 'package:http/http.dart' as http;

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

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      builder: (_, child) => Portal(child: child!),
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

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

  final String? title;

  [@override](/user/override)
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  GlobalKey<FlutterMentionsState> key = GlobalKey<FlutterMentionsState>();

  Future<List<Map<String, dynamic>>> sampleRequest(query) async {
    var url = Uri.parse('https://api.publicapis.org/entries?title=$query');
    var response = await http.get(url);
    if (response.statusCode == 200) {
      final data = json.decode(response.body);
      var apis = <Map<String, dynamic>>[];
      for (var i = 0; i < min(data['entries']?.length ?? 0, 10); i++) {
        apis.add(Map<String, dynamic>.from(data['entries'][i]));
      }
      print(apis);
      return apis;
    } else {
      print('Request failed with status: ${response.statusCode}.');
      return [];
    }
  }

  String text = "[@ruki](/user/ruki)#reactjs[@API](/user/API)#javascript#API#API-pop";

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title!),
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.end,
        children: <Widget>[
          AnnotatedText(
            text: text,
            annotationStyles: {
              '@': TextStyle(color: Colors.amber),
              '#': TextStyle(color: Colors.blue),
            },
          ),
          ElevatedButton(
            child: Text('Get Text'),
            onPressed: () {
              print(key.currentState!.controller!.markupText);
            },
          ),
          Container(
            child: FlutterMentions(
              key: key,
              suggestionPosition: SuggestionPosition.Top,
              maxLines: 5,
              minLines: 1,
              forceListHeight: true,
              decoration: InputDecoration(hintText: 'hello'),
              onAsyncSearchChanged: (trigger, value) {
                if (trigger == '@' && value.length > 0) {
                  return sampleRequest(value);
                }
                return Future.value([]);
              },
              suggestionListHeight: MediaQuery.of(context).size.height,
              mentions: [
                Mention(
                  trigger: '@',
                  style: TextStyle(
                    color: Colors.amber,
                  ),
                  useAsync: true,
                  matchAll: false,
                  displayTarget: 'API',
                  displayId: "API",
                  suggestionBuilder: (data) {
                    return ListTile(
                      title: Text(data['API']),
                      leading: CircleAvatar(
                        backgroundImage: NetworkImage(data['Description']),
                      ),
                    );
                  },
                ),
                Mention(
                  trigger: '#',
                  disableMarkup: true,
                  style: TextStyle(
                    color: Colors.blue,
                  ),
                  data: [
                    {'id': 'reactjs', 'display': 'reactjs'},
                    {'id': 'javascript', 'display': 'javascript'},
                  ],
                  matchAll: true,
                )
              ],
            ),
          ),
        ],
      ),
    );
  }
}

更多关于Flutter文本提及插件ruki_flutter_mentions的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

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


当然,下面是一个关于如何使用 ruki_flutter_mentions 插件在 Flutter 应用中实现文本提及功能的代码示例。这个插件允许你在文本输入框中识别并高亮显示提及的用户或其他实体。

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

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

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

接下来,是一个简单的示例代码,展示如何在 Flutter 应用中使用 ruki_flutter_mentions 插件:

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

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

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

class MentionsScreen extends StatefulWidget {
  @override
  _MentionsScreenState createState() => _MentionsScreenState();
}

class _MentionsScreenState extends State<MentionsScreen> {
  final List<String> users = ['Alice', 'Bob', 'Charlie', 'David'];
  final TextEditingController controller = TextEditingController();
  final FocusNode focusNode = FocusNode();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Mentions Example'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: MentionsTextField(
          controller: controller,
          focusNode: focusNode,
          decoration: InputDecoration(
            border: OutlineInputBorder(),
            hintText: 'Type @ to mention someone...',
          ),
          trigger: '@',
          suggestions: users,
          onMentionSelected: (mention) {
            // 当用户选择一个提及时,可以在这里处理
            print('Mention selected: $mention');
          },
          onTextChanged: (text) {
            // 当文本变化时,可以在这里处理
            print('Text changed: $text');
          },
          suggestionBuilder: (context, mention) {
            return ListTile(
              leading: CircleAvatar(child: Text(mention[0])),
              title: Text(mention),
              onTap: () {
                // 插入提及到文本中
                controller.value = TextEditingValue(
                  text: controller.text + mention + ' ',
                  selection: TextSelection.fromPosition(
                    TextPosition(
                      offset: controller.text.length + mention.length + 1,
                    ),
                  ),
                );
              },
            );
          },
        ),
      ),
    );
  }

  @override
  void dispose() {
    controller.dispose();
    focusNode.dispose();
    super.dispose();
  }
}

在这个示例中:

  1. 我们创建了一个 MentionsScreen 小部件,它包含一个 MentionsTextField
  2. users 列表包含可以被提及的用户名。
  3. MentionsTextFieldtrigger 属性设置为 @,这意味着用户需要在文本中输入 @ 来触发提及功能。
  4. suggestions 属性提供了可以被提及的用户列表。
  5. onMentionSelected 回调函数在用户选择一个提及时被调用。
  6. onTextChanged 回调函数在文本变化时被调用。
  7. suggestionBuilder 用于构建每个提及建议的显示样式,当用户点击一个建议时,它会将该提及插入到文本中。

这个示例展示了如何配置和使用 ruki_flutter_mentions 插件来实现基本的文本提及功能。你可以根据需要对代码进行扩展和自定义,以满足你的应用需求。

回到顶部