Flutter桌面端开发——发送本地悬浮通知?
在我用的大部分桌面端中,发送本地悬浮通知的软件可以说是屈指可数。但是,这不妨碍到我们学习✊,奋斗说不定以后就能用到呢!
在选择该使用哪些插件开发桌面端的时候,由 lijy91 主导的 LeanFlutter 可以说是帮了很大的忙,有需要的可以自己去看看。
接下来要介绍的两个发送通知的插件,也是从 LeanFlutter 下的 awesome-flutter-desktop 仓库中找的。
local_notifier
安装🛠
点击local_notifier获取最新版本。以下是在编写本文章时的最新版本:
local_notifier: ^0.1.1
👻注意:在开发 Linux 端的程序时,还需要额外的操作,具体可以查看这里
使用🍖
要想实现发送通知的功能,需要用到一个实例化的 LocalNotifier 对象:
final localNotifier = LocalNotifier.instance;
如果你想全局使用,可以把该行代码放到一个自定义的全局类里。
要想编辑想发送的内容,需要用到 LocalNotification 类。实例化该类可以传入5个参数:
String? identifier
:用来当做通用唯一识别码required String title
:发送通知的标题,一般是软件名称String? subtitle
:发送的通知内容的标题String? body
:发送的内容的主体bool silent = false
:在发送通知时是否静音
final notification = LocalNotification(
identifier: '12345',
title: '古诗鉴赏从',
subtitle: '桃夭 - 佚名〔先秦〕',
body: '桃之夭夭,灼灼其华。之子于归,宜其室家。\n桃之夭夭,有蕡其实。之子于归,宜其家室。\n桃之夭夭,其叶蓁蓁。之子于归,宜其家人。',
silent: false,
);
localNotifier.notify(notification);
现在我们就能愉快地发送一条自定义的通知了🎉
我们发现,其中其实只有title参数是必传的,我们就试一下只传入这个参数:
final notification = LocalNotification(
title: '古诗鉴赏从',
);
localNotifier.notify(notification);
我们发现,只传 title 参数,它会自动将 title 的参数值赋值给 subtitle,而 body 参数会以“新通知”代替。
好了,以上就是 local_notifier 目前的全部功能,如果你只是简单的发送一条提示使用该插件完全够用。
win_toast
安装🛠
点击win_toast获取最新版本。以下是在编写本文章时的最新版本:
win_toast: ^0.0.2
使用🍖
在全局使用该插件,需要在app初始化时初始化。在某个页面使用,只要在页面初始化时初始化就行。
初始化时需要传递3个参数:
required String appName
:程序名称required String productName
:产品名称required String companyName
:公司名称
await WinToast.instance().initialize(
appName: '第一个Desktop应用',
productName: '第一个Desktop应用',
companyName: 'Hiden Intelligence',
);
没写过原生,插件作者贴出Pick a unique AUMID that will identify your Win32 app告诉我们为什么要填这些内容👀,想了解的可以看一下。
要想发送一条通知,需要使用 showToast 方法,该方法有5个参数可以传:
required ToastType type
:传入toast显示的类型,一共有8种:- imageAndText01至imageAndText04
- text01至text04
至于这些类型的异同,可以点这里👀
required String title
:通知显示的标题String subtitle = ''
:通知显示的主要内容String imagePath = ''
:选择 imageAndText 类型时,要显示的图片List actions = const []
:显示通知中的按钮
使用text类型
先定义几个变量和常量:
Toast? toast;
final List<String> _title = 'Shining For One Thing(《一闪一闪亮星星》影视剧歌曲) - 赵贝尔';
final List<String> _subtitle = 'I fall in love\nI see your love\n遇见你才发现\n我在等你到来';
final List<String> _actione = ['上一首', '播放/暂停', '下一首'];
先来看看只传入文字的 text01 类型:
toast = await WinToast.instance().showToast(
type: ToastType.text01,
title: _title,
actions: _actione,
);
👻注意:当使用 ToastType.text01 或 ToastType.imageAndText01 时不能传入 subtitle 参数。
再来看看只传入文字的 text02 类型:
toast = await WinToast.instance().showToast(
type: ToastType.text02,
title: _title,
subtitle: _subtitle,
actions: _actione,
);
用了一下 ToastType.text03 和 ToastType.text04,发现显示的效果和 ToastType.text02 没有差别。大家可以自己试试。
使用imageAndText类型
修改一下常量的值(非必要):
Toast? toast;
final List<String> _title = '又下雨了,你的心情怎么样?';
final List<String> _subtitle = '偷偷告诉你,明天就天晴了😏\n好雨知时节,当春乃发生。随风潜入夜,润物细无声。野径云俱黑,江船火独明。晓看红湿处,花重锦官城。';
final List<String> _actione = ['不开森😭', '只想睡觉🥱', '非常高兴😃'];
还需要传入一张图片,目前无法得知应该传入图片的路径怎么填,所以先准备一张资源图片传入它的相对路径:
final String _imagePath = 'assets/images/pdx.jpg';
来看看 imageAndText01 类型:
toast = await WinToast.instance().showToast(
type: ToastType.imageAndText01,
title: _titles * 3,
imagePath: _imagePath,
actions: _action,
);
😲嗯?我们传入的图片怎么没显示?换个网络图片的链接试试:
final String _imagePath = 'https://gitee.com/ilgnefz/image-house/raw/master/images/pdx.jpg';
发现效果还是一样的。通过查看文档里的第一个链接中的例子,可以发现,这里需要传入图片的绝对路径。
那在 Flutter 中怎么获取文件的绝对路径呢🤔?当然,可以直接在 Android Studio 中选中图片点右键的 Copy Path,但是程序被打包安装后就不一定在这个位置了。学过Node.js,在里面获取文件的绝对路径要用到 Path 模块,那么 Flutter 是否也用同样的插件。打开 pub.dev 搜索,还真有。复制到 pubspec.yaml 进行安装,报错,告诉我们 Flutter Desktop 中已经集成了该插件,但是版本不一样。😀那不就好办了,第一步导入:
import 'package:path/path.dart' as path;
path 中没有 __dirname
方法,可以通过path.
查看提示,发现有一个 current
的方法。虽然我们不知道这个方法是干什么的,但也不妨试试。修改 imagePath 为如下代码:
final String _imagePath = path.join(path.current, 'assets/images/pdx.jpg');
成功🎉🎉🎉🎉🎉
接下来使用 imageAndText02 类型来看看:
toast = await WinToast.instance().showToast(
type: ToastType.imageAndText02,
title: _titles,
subtitle: _subtitle,
imagePath: _imagePath,
actions: _action,
);
imageAndText03 和 imageAndText04 显示的效果也和 imageAndText02 无差别,这里就不放图了。
大家可能已经发现,通知中的3个按钮是由 actions 参数决定的,但是这个参数传入的是 String 类型,那我们要怎么才能获取到用户对这些按钮的点击事件呢?
前期我们定义了一个toast
对象用来赋值,接下来就要用到这个参数:
if (toast != null) {
toast.eventStream.listen((event) {
if (event is ActivatedEvent) {
print(event);
}
});
}
在这里我们会获得一个 event 对象,通过打印会发现该对象下面只有一个属性actionIndex
,返回的是 int? 类型。通过该属性,我们就可以获取到用户点击的是第几个按钮:
WinToast.instance().bringWindowToFront(); // 用户点击后关闭弹窗通知
BotToast.showText(text: '你当前的状态是${_action[event.actionIndex!]}');
知道了用户点击的是哪个按钮,接下来编写事件的代码就容易了。
🛫OK,以上就是这篇文章的全部内容,仅针对插件的当前版本,并不能保证适用于以后插件用法的更新迭代。本人只处于对代码的实践部分,如某些内容的概念或叫法出错还请指正🙏。
最后,感谢 lijy91 和 boyan01 对以上插件的维护和开发😁。本程序相关代码已上传至 github 和 gitee,有需要的可以下载下来查看学习。
作者:菠萝橙子丶
链接:https://juejin.cn/post/7074482758747160590
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。