欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
一、fluttertoast 库简介
fluttertoast 是一个轻量级的消息提示插件,提供两种提示方式:原生 Toast(通过 MethodChannel 调用平台原生能力)和纯 Dart 实现的 FToast(基于 Overlay 的自定义 Toast)。无论是简单的操作反馈还是复杂的自定义提示,fluttertoast 都能满足需求。
📋 fluttertoast 核心特点
| 特点 | 说明 |
|---|---|
| 原生 Toast | 通过 MethodChannel 调用平台原生 Toast 能力 |
| 自定义 Toast | FToast 基于 Overlay 实现,完全自定义 UI |
| Toast 队列 | 自动管理多个 Toast 的显示顺序 |
| 位置控制 | 支持顶部、底部、居中等多种位置 |
| 样式定制 | 支持背景色、文字颜色、字体大小 |
| 动画效果 | 内置淡入淡出动画 |
| 跨平台兼容 | 支持 Android、iOS、Web、OpenHarmony |
平台功能支持对比
| 功能 | Android | iOS | Web | OpenHarmony |
|---|---|---|---|---|
| 原生 Toast | ✔️ | ✔️ | ❌ | ✔️ |
| 自定义 FToast | ✔️ | ✔️ | ✔️ | ✔️ |
| Toast 队列 | ✔️ | ✔️ | ✔️ | ✔️ |
| 位置控制 | ✔️ | ✔️ | ✔️ | ✔️ |
| 样式定制 | ✔️ | ✔️ | ✔️ | ✔️ |
| 取消 Toast | ✔️ | ✔️ | ✔️ | ✔️ |
使用场景
- 操作成功/失败反馈
- 表单验证提示
- 网络请求状态提示
- 自定义通知卡片
- 排队消息提示
二、OpenHarmony 适配版本
2.1 环境说明
| 组件 | 版本 |
|---|---|
| Flutter | 3.27.5 |
| HarmonyOS | 6.0 |
| fluttertoast | 8.2.8 (OpenHarmony 适配版本) |
2.2 引入方式
在 pubspec.yaml 文件中添加以下依赖配置:
yaml
dependencies:
flutter:
sdk: flutter
# fluttertoast OpenHarmony 适配版本
fluttertoast:
git:
url: https://atomgit.com/openharmony-sig/flutter_fluttertoast.git
ref: br_8.2.8_ohos
2.3 获取依赖
配置完成后,在项目根目录执行:
bash
flutter pub get
三、核心 API 讲解
3.1 Fluttertoast 类
Fluttertoast 提供原生 Toast 提示功能,通过 MethodChannel 与平台侧通信。
showToast 方法
dart
static Future<bool?> showToast({
required String msg,
Toast? toastLength,
int timeInSecForIosWeb = 1,
double? fontSize,
String? fontAsset,
ToastGravity? gravity,
Color? backgroundColor,
Color? textColor,
bool webShowClose = false,
webBgColor = "linear-gradient(to right, #00b09b, #96c93d)",
webPosition = "right",
})
参数说明:
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
| msg | String | 是 | - | Toast 显示的消息内容 |
| toastLength | Toast? | 否 | Toast.LENGTH_SHORT | Toast 显示时长 |
| timeInSecForIosWeb | int | 否 | 1 | iOS/Web 平台显示时间(秒) |
| fontSize | double? | 否 | null | 字体大小 |
| fontAsset | String? | 否 | null | 自定义字体资源路径 |
| gravity | ToastGravity? | 否 | ToastGravity.BOTTOM | Toast 显示位置 |
| backgroundColor | Color? | 否 | Colors.black | 背景颜色 |
| textColor | Color? | 否 | Colors.white | 文字颜色 |
| webShowClose | bool | 否 | false | Web 平台是否显示关闭按钮 |
| webBgColor | String | 否 | 渐变绿色 | Web 平台背景样式 |
| webPosition | String | 否 | "right" | Web 平台显示位置 |
cancel 方法
dart
static Future<bool?> cancel()
说明: 立即取消当前显示的 Toast。
3.2 Toast 枚举
dart
enum Toast {
LENGTH_SHORT, // 短提示,约 1 秒
LENGTH_LONG, // 长提示,约 5 秒
}
3.3 ToastGravity 枚举
dart
enum ToastGravity {
TOP, // 顶部
BOTTOM, // 底部
CENTER, // 居中
TOP_LEFT, // 左上
TOP_RIGHT, // 右上
BOTTOM_LEFT, // 左下
BOTTOM_RIGHT, // 右下
CENTER_LEFT, // 左中
CENTER_RIGHT, // 右中
SNACKBAR, // 底部(类似 Snackbar)
NONE, // 无位置偏移
}
3.4 FToast 类
FToast 是纯 Dart 实现的自定义 Toast,不依赖平台原生能力,基于 Overlay 实现。
主要方法
dart
// 初始化(必须调用)
FToast init(BuildContext context)
// 显示自定义 Toast
void showToast({
required Widget child,
PositionedToastBuilder? positionedToastBuilder,
Duration toastDuration = const Duration(seconds: 2),
ToastGravity? gravity,
Duration fadeDuration = const Duration(milliseconds: 350),
bool ignorePointer = false,
bool isDismissable = false,
})
// 立即移除当前 Toast
void removeCustomToast()
// 清除队列中所有 Toast
void removeQueuedCustomToasts()
参数说明:
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
| child | Widget | 是 | - | 自定义 Toast 内容 |
| positionedToastBuilder | 回调 | 否 | null | 自定义位置构建器 |
| toastDuration | Duration | 否 | 2 秒 | 显示时长 |
| gravity | ToastGravity? | 否 | null | 显示位置 |
| fadeDuration | Duration | 否 | 350 毫秒 | 淡入淡出动画时长 |
| ignorePointer | bool | 否 | false | 是否忽略点击事件 |
| isDismissable | bool | 否 | false | 是否可点击关闭 |
Toast 队列机制
FToast 内部维护一个队列,多次调用 showToast 会依次显示,不会重叠。
四、完整使用示例

dart
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
void main() {
runApp(const FlutterToastApp());
}
class FlutterToastApp extends StatelessWidget {
const FlutterToastApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Toast 消息中心',
debugShowCheckedModeBanner: false,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: const Color(0xFF6C63FF)),
useMaterial3: true,
),
home: const FlutterToastHomePage(),
builder: FToastBuilder(),
);
}
}
class FlutterToastHomePage extends StatefulWidget {
const FlutterToastHomePage({super.key});
@override
State<FlutterToastHomePage> createState() => _FlutterToastHomePageState();
}
class _FlutterToastHomePageState extends State<FlutterToastHomePage> {
late FToast _fToast;
@override
void initState() {
super.initState();
_fToast = FToast();
_fToast.init(context);
}
void _showNativeToast({
required String msg,
Toast length = Toast.LENGTH_SHORT,
ToastGravity gravity = ToastGravity.BOTTOM,
Color bgColor = Colors.black,
Color textColor = Colors.white,
}) {
Fluttertoast.showToast(
msg: msg,
toastLength: length,
gravity: gravity,
backgroundColor: bgColor,
textColor: textColor,
fontSize: 16.0,
);
}
void _showCustomToast({
required String title,
required String message,
required IconData icon,
required Color color,
ToastGravity gravity = ToastGravity.BOTTOM,
}) {
_fToast.showToast(
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.1),
blurRadius: 8,
offset: const Offset(0, 2),
),
],
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: color.withOpacity(0.1),
borderRadius: BorderRadius.circular(8),
),
child: Icon(icon, color: color),
),
const SizedBox(width: 12),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(
title,
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 14,
),
),
const SizedBox(height: 2),
Text(
message,
style: TextStyle(
fontSize: 12,
color: Colors.grey[600],
),
),
],
),
],
),
),
gravity: gravity,
toastDuration: const Duration(seconds: 3),
isDismissable: true,
);
}
void _showQueuedToasts() {
_fToast.removeQueuedCustomToasts();
final items = [
{'title': '步骤 1', 'msg': '正在初始化...', 'icon': Icons.settings, 'color': Colors.blue},
{'title': '步骤 2', 'msg': '正在加载数据...', 'icon': Icons.download, 'color': Colors.orange},
{'title': '步骤 3', 'msg': '正在处理...', 'icon': Icons.analytics, 'color': Colors.purple},
{'title': '完成', 'msg': '所有操作已完成', 'icon': Icons.check_circle, 'color': Colors.green},
];
for (final item in items) {
_fToast.showToast(
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.1),
blurRadius: 8,
offset: const Offset(0, 2),
),
],
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(item['icon'] as IconData, color: item['color'] as Color),
const SizedBox(width: 12),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(
item['title'] as String,
style: const TextStyle(fontWeight: FontWeight.bold),
),
Text(
item['msg'] as String,
style: TextStyle(fontSize: 12, color: Colors.grey[600]),
),
],
),
],
),
),
gravity: ToastGravity.CENTER,
toastDuration: const Duration(seconds: 2),
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Toast 消息中心'),
backgroundColor: const Color(0xFF6C63FF),
foregroundColor: Colors.white,
),
body: ListView(
padding: const EdgeInsets.all(16),
children: [
_buildSectionTitle('原生 Toast'),
_buildActionCard(
icon: Icons.check_circle,
title: '成功提示',
subtitle: '操作成功,短提示',
color: const Color(0xFF4CAF50),
onTap: () => _showNativeToast(
msg: '操作成功!',
length: Toast.LENGTH_SHORT,
bgColor: const Color(0xFF4CAF50),
),
),
_buildActionCard(
icon: Icons.error,
title: '错误提示',
subtitle: '操作失败,长提示',
color: const Color(0xFFF44336),
onTap: () => _showNativeToast(
msg: '操作失败,请重试!',
length: Toast.LENGTH_LONG,
bgColor: const Color(0xFFF44336),
),
),
_buildActionCard(
icon: Icons.info,
title: '居中提示',
subtitle: '消息居中显示',
color: const Color(0xFF2196F3),
onTap: () => _showNativeToast(
msg: '这是一条居中的消息',
gravity: ToastGravity.CENTER,
bgColor: const Color(0xFF2196F3),
),
),
_buildActionCard(
icon: Icons.warning,
title: '顶部提示',
subtitle: '消息顶部显示',
color: const Color(0xFFFF9800),
onTap: () => _showNativeToast(
msg: '请注意查看此消息',
gravity: ToastGravity.TOP,
bgColor: const Color(0xFFFF9800),
),
),
const SizedBox(height: 24),
_buildSectionTitle('自定义 FToast'),
_buildActionCard(
icon: Icons.notifications,
title: '通知样式',
subtitle: '自定义卡片样式 Toast',
color: const Color(0xFF6C63FF),
onTap: () => _showCustomToast(
title: '新消息',
message: '您有一条新的系统通知',
icon: Icons.notifications,
color: const Color(0xFF6C63FF),
),
),
_buildActionCard(
icon: Icons.security,
title: '安全提示',
subtitle: '带图标的自定义 Toast',
color: const Color(0xFF00BCD4),
onTap: () => _showCustomToast(
title: '安全提醒',
message: '请妥善保管您的账号信息',
icon: Icons.security,
color: const Color(0xFF00BCD4),
gravity: ToastGravity.TOP,
),
),
const SizedBox(height: 24),
_buildSectionTitle('Toast 队列'),
_buildActionCard(
icon: Icons.queue_play_next,
title: '队列演示',
subtitle: '依次显示 4 条消息',
color: const Color(0xFF9C27B0),
onTap: _showQueuedToasts,
),
_buildActionCard(
icon: Icons.clear_all,
title: '清除队列',
subtitle: '移除所有待显示的 Toast',
color: const Color(0xFF795548),
onTap: () {
_fToast.removeQueuedCustomToasts();
_showNativeToast(
msg: '已清除队列',
bgColor: const Color(0xFF795548),
);
},
),
const SizedBox(height: 32),
],
),
);
}
Widget _buildSectionTitle(String title) {
return Padding(
padding: const EdgeInsets.only(bottom: 12),
child: Text(
title,
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Color(0xFF6C63FF),
),
),
);
}
Widget _buildActionCard({
required IconData icon,
required String title,
required String subtitle,
required Color color,
required VoidCallback onTap,
}) {
return Card(
child: ListTile(
leading: CircleAvatar(
backgroundColor: color.withOpacity(0.1),
child: Icon(icon, color: color),
),
title: Text(title),
subtitle: Text(subtitle),
trailing: const Icon(Icons.chevron_right),
onTap: onTap,
),
);
}
}
五、适配要点
5.1 OpenHarmony 平台特性
-
原生 Toast
- OpenHarmony 平台通过 MethodChannel 实现原生 Toast
- 支持基本的消息显示、位置控制、样式定制
toastLength控制显示时长
-
FToast 自定义 Toast
- FToast 是纯 Dart 实现,不依赖平台原生能力
- 基于 Overlay 实现,所有平台行为一致
- 支持完全自定义 Widget 作为 Toast 内容
-
Toast 队列
- FToast 内部维护队列,多次调用会依次显示
- 使用
removeQueuedCustomToasts()可清除队列 - 适合需要顺序展示多个提示的场景
-
MaterialApp 配置
- 使用 FToast 需要在 MaterialApp 的 builder 中添加
FToastBuilder() - 否则可能无法正确获取 Overlay
- 使用 FToast 需要在 MaterialApp 的 builder 中添加
5.2 与 Android/iOS 的差异
| 差异点 | Android/iOS | OpenHarmony |
|---|---|---|
| 原生 Toast | 完整支持 | 支持 |
| 自定义字体 | 支持 | 支持 |
| FToast | 完整支持 | 完整支持 |
| Toast 队列 | 完整支持 | 完整支持 |
| Web 特性 | 支持渐变背景等 | 不适用 |
5.3 注意事项
-
FToast 初始化
- 必须在
initState中调用_fToast.init(context) - MaterialApp 需要配置
builder: FToastBuilder()
- 必须在
-
Context 问题
- FToast 需要有效的 BuildContext
- 避免使用 Navigator 或 MaterialApp 的顶层 context
-
队列管理
- 多次调用
showToast会加入队列依次显示 - 使用
removeCustomToast()可立即隐藏当前 Toast - 使用
removeQueuedCustomToasts()可清除所有待显示 Toast
- 多次调用
-
原生 Toast 限制
- 原生 Toast 不支持自定义 Widget
- 只能显示文本,样式有限
- 需要自定义样式时使用 FToast
六、常见问题
Q1: FToast 提示 Context is null?
原因: 未调用 init(context) 或 context 无效。
解决方案:
dart
@override
void initState() {
super.initState();
_fToast = FToast();
_fToast.init(context);
}
Q2: FToast 提示 Overlay is null?
原因: MaterialApp 未配置 builder 或使用了顶层 context。
解决方案:
dart
MaterialApp(
builder: FToastBuilder(),
home: const MyHomePage(),
)
Q3: 如何立即隐藏 Toast?
解决方案:
dart
// 隐藏原生 Toast
Fluttertoast.cancel();
// 隐藏自定义 Toast
_fToast.removeCustomToast();
Q4: 如何让 Toast 可点击关闭?
解决方案:
dart
_fToast.showToast(
child: YourCustomWidget(),
isDismissable: true, // 允许点击关闭
toastDuration: const Duration(seconds: 3),
);
Q5: 如何自定义 Toast 位置?
解决方案:
dart
// 使用 gravity 参数
_fToast.showToast(
child: YourCustomWidget(),
gravity: ToastGravity.TOP, // 或 BOTTOM, CENTER 等
);
// 使用 positionedToastBuilder 完全自定义
_fToast.showToast(
child: YourCustomWidget(),
positionedToastBuilder: (context, child) {
return Positioned(
top: 200,
left: 50,
child: child,
);
},
);
Q6: 原生 Toast 和 FToast 如何选择?
解决方案:
- 原生 Toast:简单文本提示,不需要自定义样式
- FToast:需要自定义样式、图标、队列管理
dart
// 简单提示用原生
Fluttertoast.showToast(msg: '操作成功');
// 复杂提示用 FToast
_fToast.showToast(
child: CustomToastWidget(),
isDismissable: true,
);
七、总结
fluttertoast 是一个功能丰富的消息提示库,在 OpenHarmony 平台的适配已经非常成熟。通过本文的介绍,你应该已经掌握了:
- Fluttertoast 原生 Toast 的使用方法和参数配置
- FToast 自定义 Toast 的初始化和显示流程
- Toast 队列机制和管理方法
- 完整的应用级别消息提示中心实现
- OpenHarmony 平台的适配要点和注意事项
- 常见问题和解决方案
在实际开发中,建议根据具体需求选择合适的 Toast 类型。简单的文本提示使用原生 Toast,需要自定义样式或队列管理时使用 FToast。同时注意正确初始化 FToast 并配置 MaterialApp 的 builder。
💡 提示: 更多 OpenHarmony 适配的 Flutter 三方库信息,请访问 开源鸿蒙跨平台开发者社区 获取最新资源和技术支持。