注意:查看本文章前請先查看更新日志,以至於該文章適合插件的最新版本
更新日志
詳情 | 日期 |
---|---|
更新了win_toast版本 | 2022-12-10 |
更新了local_notifier在0.1.5版本的用法 | 2022-06-13 |
在我用的大部分桌面端中,發送本地懸浮通知的軟件可以說是屈指可數。但是,這不妨礙到我們學習✊,奮斗說不定以后就能用到呢!
在選擇該使用哪些插件開發桌面端的時候,由 lijy91 主導的 LeanFlutter 可以說是幫了很大的忙,有需要的可以自己去看看。
接下來要介紹的兩個發送通知的插件,也是從 LeanFlutter 下的 awesome-flutter-desktop 倉庫中找的。
local_notifier
安裝🛠
點擊local_notifier獲取最新版本。以下是在編寫本文章時的最新版本:
local_notifier: ^0.1.5
👻注意:在開發 Linux 端的程序時,還需要額外的操作,具體可以查看這里
使用🍖
要想實現發送通知的功能,需要用到一個實例化的 LocalNotifier 對象,並調用setAppName方法:
void main() async{
WidgetsFlutterBinding.ensureInitialized();
await localNotifier.setup(
appName: 'Flutter桌面應用',
// 僅 Windows
shortcutPolicy: ShortcutPolicy.requireCreate,
);
runApp(const MyApp());
}
setup
方法有兩個參數可以傳入:
String appName
:應用程序的名稱shortcutPolicy shortcutPolicy
:該屬性一共有3個值:ignore
:不檢查、創建或修改快捷方式requireNoCreate
:需要與 AUMI 匹配的快捷方式,不要創建或修改現有的快捷方式requireNoCreate
:默認值。需要具有匹配 AUMI 的快捷方式,如果缺少則創建,如果不匹配則修改
要想編輯想發送的內容,需要用到 LocalNotification 類。實例化該類可以傳入6個參數:
String? identifier
:用來當做通用唯一識別碼required String title
:發送通知的標題,一般是軟件名稱String? subtitle
:發送的通知內容的標題String? body
:發送的內容的主體bool silent = false
:在發送通知時是否靜音List<LocalNotificationAction>? actions
:通知中顯示的按鈕
實例化后的對象有5個方法:
onShow
:通知顯示時調用onClose
:通知關閉時調用onClick
:通知點擊時調用onClickAction
:通知中的按鈕被點擊時調用show
:顯示通知
void _localNot() {
final notification = LocalNotification(
// 用來生成通用唯一識別碼
identifier: '12345',
title: '古詩鑒賞從',
subtitle: '桃夭 - 佚名〔先秦〕',
body: '桃之夭夭,灼灼其華。之子於歸,宜其室家。\n桃之夭夭,有蕡其實。之子於歸,宜其家室。\n桃之夭夭,其葉蓁蓁。之子於歸,宜其家人。',
// 用來設置是否靜音
silent: true,
);
notification.onShow = () {
BotToast.showText(text: '顯示了一條通知');
};
notification.onClose = () {
BotToast.showText(text: '通知已經關閉');
};
notification.onClick = () {
BotToast.showText(text: '通知被點擊了');
};
notification.onClickAction = (index) {
BotToast.showText(text: '你點擊了通知的第$index個選項');
};
notification.show();
}
現在我們就能愉快地發送一條自定義的通知了🎉
其中只有title參數是必傳的,我們就試一下只傳入這個參數:
final notification = LocalNotification(
identifier: '12345',
title: '古詩鑒賞從',
);
notification.show();
我們發現,只傳 title 參數,它會自動將 title 的參數值賦值給 subtitle,而 body 參數會以“新通知”代替。而且onClose和onClick兩個方法都會觸發關閉通知的功能,但是不會同時調用。這兩個操作其實是有區別的。
由以上試驗可得,onClick才會真正一次性把通知刪除,而onClose只會把通知收起來,需要再次調用onClose才能關閉通知。
接下來來看看LocalNotificationAction對象,它有2個可選參數:
String type
:通知中顯示動作的類型,值為buttonString? text
:按鈕中顯示的文本。雖然是可選,但是必填,否則會出錯
final notification = LocalNotification(
...
actions: [
LocalNotificationAction(text: '學廢了'),
LocalNotificationAction(text: '沒學廢'),
],
);
我們可以發現,點擊的按鈕可以通過onClickAction獲取到,然后就可以愉快地編寫按鈕點擊后的操作了。😁
win_toast
該插件0.2.0以后用法有較大差距,通過xml文件來自定義通知樣式,需要的可以自行查看官方文檔和案例。這里只記錄到0.1.1的用法。
安裝🛠
點擊win_toast獲取最新版本。以下是在編寫本文章時的最新版本:
win_toast: ^0.1.0
使用🍖
在全局使用該插件,需要在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,有需要的可以下載下來查看學習。