Flutter插件mfm的特性与使用方法
概述
此插件是用于Flutter的MFM渲染器。MFM是一种类似于Markdown的标记语言,主要用于Misskey平台。该插件不依赖于WebView。
功能特性
该插件支持以下MFM语法:
- 引用块(
>
) - 代码块(内联、块)
mfm_renderer
不会高亮代码块,可以使用来自pub.dev
的任何高亮库。
- 居中块
- 文本装饰(加粗、大号字体、斜体、小号字体、更改字体、删除线、背景色、前景色)
- 表情符号代码、Unicode表情符号代码
mfm_render
不会构建Image
小部件,可以通过传递builder
参数到MFM小部件。
- 纯文本内联块
- 数学块、数学内联块
- Misskey不支持这些语法但未进行处理。
- 提及、标签、URL链接
- 搜索语法
- 翻译项目(
$[scale
、$[position
、$[flip
) - 模糊效果
- 注音(
$[ruby]
) - 显示绝对时间(
$[unixtime]
) - MFM动画
rainbow
、shake
、jelly
、twitch
、bounce
、jump
、spin
和spakle
- 将某些项目喵化(如将
なんなん
转换为にゃんにゃん
) - 内联边框(
$[border]
)
开始使用
在pubspec.yaml
文件中添加依赖项:
flutter pub add mfm
使用示例
以下是一个完整的示例,展示如何在Flutter应用中使用mfm插件。
示例代码
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_highlighting/flutter_highlighting.dart';
import 'package:flutter_highlighting/themes/github-dark.dart';
import 'package:highlighting/languages/all.dart';
import 'package:mfm/mfm.dart';
import 'package:http/http.dart' as http;
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text("MFM Rendering Example")),
body: const MfmRenderingExample(),
),
);
}
}
class MfmRenderingExample extends StatefulWidget {
const MfmRenderingExample({super.key});
[@override](/user/override)
State<StatefulWidget> createState() => MfmRenderingExampleState();
}
class MfmRenderingExampleState extends State<MfmRenderingExample> {
final textController = TextEditingController();
Map<String, String> emojiList = {};
final focusNode = FocusNode();
[@override](/user/override)
void initState() {
super.initState();
textController.addListener(() {
setState(() {});
});
}
[@override](/user/override)
void didChangeDependencies() {
super.didChangeDependencies();
Future(() async {
String? host;
await showDialog(
context: context,
builder: (context) => AlertDialog(
content: TextFormField(
onFieldSubmitted: (data) {
host = data;
Navigator.of(context).pop();
},
decoration: const InputDecoration(
hintText:
"请输入Misskey服务器主机名(例如misskey.io)以获取表情符号。"),
),
),
);
if (host == null) return;
final response = await http.get(
Uri(scheme: "https", host: host, pathSegments: ["api", "emojis"]));
setState(() {
emojiList = Map.fromEntries(
(jsonDecode(response.body)["emojis"] as List)
.map((e) => MapEntry(e["name"] as String, e["url"] as String)));
focusNode.requestFocus();
});
});
}
[@override](/user/override)
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: TextField(
controller: textController,
maxLines: null,
expands: true,
focusNode: focusNode,
keyboardType: TextInputType.multiline,
decoration:
const InputDecoration(contentPadding: EdgeInsets.all(10)),
),
),
Expanded(
child: DecoratedBox(
decoration: BoxDecoration(
border: Border(
left: BorderSide(color: Theme.of(context).dividerColor))),
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(10),
child: Mfm(
mfmText: textController.text,
emojiBuilder: (context, emoji, style) {
final emojiData = emojiList[emoji];
if (emojiData == null) {
return Text.rich(TextSpan(text: emoji, style: style));
} else {
// 如果找到表情符号数据,则显示
return Image.network(
emojiData,
height: (style?.fontSize ?? 1) * 2,
);
}
},
codeBlockBuilder: (context, code, lang) {
final language = allLanguages[lang]?.id ?? "javascript";
return SizedBox(
width: double.infinity,
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: HighlightView(
code,
languageId: language,
theme: githubDarkTheme,
padding: const EdgeInsets.all(10),
),
),
);
},
mentionTap: (username, host, acct) {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text("$acct tapped.")));
},
linkTap: (url) {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text("@$url tapped.")));
},
hashtagTap: (url) {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text("@$url tapped.")));
},
),
),
),
),
),
],
);
}
}
更多关于Flutter插件mfm的特性与使用方法的实战教程也可以访问 https://www.itying.com/category-92-b0.html