Most of the desktop software we use on a daily basis takes up space in the system tray. Of course, we can also achieve this effect with Flutter via third-party plug-ins.
tray_manager
Install 🛠
Click tray_Manager to get the latest version. The following is the latest version at the time of writing:
tray_manager: ^ 0.1.4
Copy the code
👻 Note: Additional operations are required when developing programs for Linux, which can be found here
Using 🥩
First instantiate the TrayManager object:
final TrayManager _trayManager = TrayManager.instance;
Copy the code
Set the icon 🐱💻
In the system tray display, of course, is the first to set an icon.
After instantiating TrayManager, we can use setIcon to set ICONS.
Here, we need to prepare images in two formats:.png and.ico. PNG images are displayed in trays on other platforms, and ICOs are displayed on Windows platforms.
final String _iconPathWin = 'assets/images/tray_manager.ico';
final String _iconPathOther = 'assets/images/tray_manager.png';
Copy the code
What if we display it in PNG format on Windows 🤔?
await _trayManager.setIcon(_iconPathOther);
Copy the code
Although 😲 occupies the position, but will not display it at all! Let’s change it to the correct format:
await _trayManager.setIcon(Platform.isWindows ? _iconPathWin : _iconPathOther);
Copy the code
This will correctly display the icon we set up 😀
Since this is the case, then we can simulate QQ and wechat to the message of the flashing effect!
Prepare two fully transparent images in different formats.
final String _iconNullWin = 'assets/images/null.ico';
final String _iconNullOther = 'assets/images/null.png';
Copy the code
To see if the icon has been set, we also need a Boolean value:
bool _hasIcon = false;
Copy the code
Change the code for setting ICONS:
void _generateIcon() async {
await _trayManager.setIcon(Platform.isWindows ? _iconPathWin : _iconPathOther);
_hasIcon = true;
}
Copy the code
Now write a method that flashes the image every 300 milliseconds, using a Timer object:
Timer? _timer;
Copy the code
Don’t forget to dispose in the dispose method:
@override
void dispose() {
// TODO: implement dispose_timer? .cancel();super.dispose();
}
Copy the code
void _iconFlash() {
_timer = Timer.periodic(const Duration(milliseconds: 300), (timer) async {
if (_hasIcon) {
await _trayManager.setIcon(Platform.isWindows ? _iconNullWin : _iconNullOther);
} else {
await_trayManager.setIcon(Platform.isWindows ? _iconPathWin : _iconPathOther); } _hasIcon = ! _hasIcon; setState(() {}); }); }Copy the code
With the method to turn on the flicker animation, you also need a method to turn off the flicker effect:
void_closeIconFlash() { _timer? .cancel(); _generateIcon(); }Copy the code
All set. Let’s see what happens.
Perfect 😎
Set the prompt message 🐾
When we mouse over the software icon in the tray area, there is usually a prompt message. Here we can also set:
void _generateToolTip() async {
await _trayManager.setToolTip('What do you want 😒');
}
Copy the code
Set the menu item 🕸
There is an icon in the tray area, but there seems to be nothing except the icon. Isn’t that pure gross? Standing pit not pull 💩. Now, let’s give it a hand.
We can set the menu using the setContextMenu method, which passes an array object of MenuItem, and then we have to figure out what the object is passing in. There are six parameters that can be passed to a MenuItem:
String? key
: Enter or leave a key as a unique identifierString? title
: The title (content) of the passed optionString? toolTip
: Passes the mouse over the option promptbool isEnabled = true
: Indicates whether to enable the optionbool isSeparatorItem = false
: Indicates whether to separate the line itemList<MenuItem>? items
: MenuItem list of invalid nesting dolls
Ok, now that we’ve got the MenuItem sorted out, let’s use it:
List<MenuItem> items = [
MenuItem(title: 'Chinese'),
MenuItem(title: 'mathematics', toolTip: 'Inescapable'),
MenuItem(title: 'English', isEnabled: false),
MenuItem.separator,
MenuItem(
key: 'science',
title: 'science',
items: [
MenuItem(title: 'physical'),
MenuItem(title: 'chemistry'),
MenuItem(title: 'biological'),
],
),
MenuItem.separator,
MenuItem(
key: 'arts',
title: 'liberal arts',
items: [
MenuItem(title: 'political'),
MenuItem(title: 'history'),
MenuItem(title: 'geographic'),],)];Copy the code
Load them up:
await trayManager.setContextMenu(items);
Copy the code
HMM 😶 how useless?? I looked at the console, and there was no error.
The menu is already set up, we just haven’t written a way to make it appear.
Register mouse events at 🐹
Under what circumstances do we make it display 🤔? Right mouse click icon! To listen for a right mouse click on an icon, let’s change the code:
class _UseTrayManagerPageState extends State<UseTrayManagerPage> with TrayListener {
@override
void initState() {
super.initState();
_trayManager.addListener(this);
}
@override
voiddispose() { _timer? .cancel(); _trayManager.removeListener(this);
super.dispose(); }... }Copy the code
By mixing the with keyword into the TrayListener class, we can do more event manipulation on the icon.
onTrayMenuItemClick
: Menu option Click eventonTrayIconRightMouseUp
: right click on the event, not try out 😕onTrayIconRightMouseDown
: icon right-click eventonTrayIconMouseUp
: supposedly left click after the event, did not try out 😕onTrayIconMouseDown
: icon Left-click event
Set the right click event:
@override
void onTrayIconRightMouseDown() async {
await _trayManager.popUpContextMenu();
}
Copy the code
Set menu options click events:
@override
void onTrayMenuItemClick(MenuItem menuItem) {
BotToast.showText(text: 'You chose${menuItem.title}');
}
Copy the code
Set icon left mouse button down event (display program) :
@override
void onTrayIconMouseDown() {
windowManager.show(a);// This method comes from the window_manager plug-in
}
Copy the code
Obtain the icon location 🐣
This method will return the position of the icon on the screen (Rect object)
await _trayManager.getBounds();
Copy the code
Remove tray area program 🦝
In addition to closing the application and removing it from the tray area, we can also actively remove it:
await _trayManager.destroy();
Copy the code
system_tray
Install 🛠
Click system_tray to get the latest version. The following is the latest version at the time of writing:
system_tray: ^ 0.1.0 from
Copy the code
👻 Note: Additional operations are required when developing programs for Linux, which can be found here
Using 🥩
Instantiate the SystemTray object:
final SystemTray _systemTray = SystemTray();
Copy the code
Initialize 🐱 💻
System_tray sets up ICONS and prompts all at once during initialization.
Let’s first prepare the constant resources to use:
final String _title = 'First Desktop Application';
final String _toolTip = 'What are you looking at?';
final String _iconPathWin = 'assets/images/system_tray.ico';
final String _iconPathOther = 'assets/images/system_tray.png';
Copy the code
The system_tray icon is set in the initialization method:
void _initTray() async {
String _iconPath = Platform.isWindows ? _iconPathWin : _iconPathOther;
await _systemTray.initSystemTray(title: _title, iconPath: _iconPath, toolTip: _toolTip);
}
Copy the code
These are all set during initialization, so how do we change them later? Don’t worry, you can use the following methods:
setImage
: Modify iconsetTooltip
: Modify promptsetTitle
: Modify the titlegetTitle
: Get the title
Get ready to change:
final String _newToolTip = "Why are you fat?";
final String _anotherIconWin = 'assets/images/another.ico';
final String _anotherIconOther = 'assets/images/another.png';
Copy the code
Get started:
void _modifyInfo() async {
String _newPath = Platform.isWindows ? _anotherIconWin : _anotherIconOther;
await _systemTray.setToolTip(_newToolTip);
await _systemTray.setImage(_newPath);
setState(() {});
}
Copy the code
Set the menu item 🕸
System_tray Sets menu items with MenuItem and SubMenu.
MenuItem can be passed three parameters:
required String label
: Indicates the displayed labelbool enabled = true
: Optional or notvoid Function()? onClicked
: Click event
SubMenu requires two parameters:
required String label
: Menu labelrequired List children
: the submenu
void _setMenu() async {
List<MenuItem> menus = [
MenuItem(label: '5', onClicked: () => _floorNumber('5')),
MenuItem(label: ' 'on the fourth floor, onClicked: () => _floorNumber(' 'on the fourth floor)),
SubMenu(
label: 'on the third floor,
children: [
MenuItem(label: 'Third floor toilet', onClicked: () => _floorNumber('Third floor toilet')),
],
),
MenuItem(label: ' 'on the second floor, onClicked: () => _floorNumber(' 'on the second floor)),
MenuItem(label: 'on the first floor, enabled: false)];await _systemTray.setContextMenu(menus);
}
Copy the code
Of course, like tray_manager, this is only set, but it doesn’t tell when to display it. So we need an event for the right mouse button icon.
Register mouse events at 🐹
There are several mouse events:
leftMouseUp
: Lift the left mouse buttonleftMouseDown
: Press the left mouse buttonleftMouseDblClk
: Double-click the left mouse buttonrightMouseUp
: Right mouse button is liftedrightMouseDown
: Press the right mouse button
void _registerEvent() {
_systemTray.registerSystemTrayEventHandler((eventName) {
if (eventName == 'leftMouseDown') {
windowManager.show(a); }else if (eventName == 'rightMouseDown') { _systemTray.popUpContextMenu(); }}); }Copy the code
🛫OK, that’s the end of this article, which is for the current version of the plug-in and is not guaranteed to be applicable to future iterations of plug-in usage.
Finally, thanks to lijy91 and Antler119 for the maintenance and development of the above plug-ins 😁.