How to Make a MacOS Native Status Bar Menu with Flutter Desktop
In the dynamic world of software development, it is becoming increasingly popular to incorporate native components into your Flutter desktop projects. Unfortunately, not everyone knows how to achieve this. One such component that many find challenging is the status bar located at the top right corner of the screen. The good news is that you can actually create a status bar menu using your application’s icons, and in this article, we’ll show you exactly how to do it.
Let’s dive right into the step-by-step guide:
Step 1: Open MacOS Side With Xcode
The first step to creating a MacOS native status bar menu with Flutter is to open the MacOS side of your Flutter project with Xcode. Xcode is Apple’s IDE (Integrated Development Environment) for both Mac and iOS applications.
Step 2: Create Assets Folder and Add Your Logo or Icon
Next, create an “Assets” folder within your project directory. This is where you will store any media files that your application needs to access, such as your logo or icons. After creating the “Assets” folder, add your logo or icons that you want to display on your status bar menu.
Step 3: Open New Folder “StatusBar”
In your Xcode, navigate to your project directory, then create a new folder within this directory. Name this new folder “StatusBar”.
Step 4: Create StatusBarExtraController.swift and Add All Codes
Within your newly created “StatusBar” folder, create a new Swift file named “StatusBarExtraController.swift”. This is where you will be writing the logic that will control the behavior of your status bar. Make sure you add all the necessary codes. These codes will vary based on what you want your status bar menu to do.
import Foundation
import AppKit
import SwiftUI
import Cocoa
class StatusBarExtraController {
private var statusBar: NSStatusBar
private var statusItem: NSStatusItem
private var mainView: NSView
init(_ view: NSView) {
self.mainView = view
statusBar = NSStatusBar()
statusItem = statusBar.statusItem(withLength: NSStatusItem.variableLength)
let iconSwiftUI = ZStack(alignment:.center) {
Rectangle()
.fill(Color.green)
.cornerRadius(10)
.padding(0)
}
let iconView = NSHostingView(rootView: iconSwiftUI)
iconView.frame = NSRect(x: 0, y: 0, width: 15, height: 15)
if let statusBarButton = statusItem.button {
statusBarButton.frame = iconView.frame
let image = NSImage(named: "example_logo_menubar")
statusBarButton.image = image
let menuItem = NSMenuItem()
menuItem.view = mainView
let menu = NSMenu()
menu.addItem(menuItem)
statusItem.menu = menu
}
}
}
Step 5: Create StatusBarContent.swift and Add All Codes
In the same “StatusBar” folder, create another Swift file named “StatusBarContent.swift”. This file will define the content of your status bar menu. Just as with the previous file, add all the necessary codes that describe what content you want in your status bar menu.
import Foundation
import SwiftUI
import FlutterMacOS
import Cocoa
import AppKit
struct StatusBarContent: View {
var body: some View {
VStack {
Text("Example App")
Button("Button1", action: {
print("Button1")
})
Button("Button2", action: {
print("Button2")
})
Button("Button3", action: {
print("Button3")
})
}
.padding()
}
}
struct StatusBarContent_Previews: PreviewProvider {
static var previews: some View {
StatusBarContent()
}
}
Step 6: Add the StatusBarExtraController Object to AppDelegate File with Code
Finally, you will need to add the StatusBarExtraController object to your AppDelegate file. The AppDelegate file is a part of the Application Life Cycle, and it is responsible for handling system-level events. These events can include things like the application being launched, moved to the background, brought to the foreground, or terminated.
import Cocoa
import SwiftUI
import FlutterMacOS
@NSApplicationMain
class AppDelegate: FlutterAppDelegate {
// add this object
var statusBarExtra: StatusBarExtraController?
override func applicationDidFinishLaunching(_ notification: Notification) {
// add these lines
let statusBarContent = StatusBarContent()
let mainExtraView = NSHostingView(rootView: statusBarContent)
mainExtraView.frame = NSRect(x: 0, y: 0, width: 120, height: 200)
statusBarExtra = StatusBarExtraController(mainExtraView)
}
override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
return true
}
}
By adding the StatusBarExtraController object to your AppDelegate file, you are ensuring that your status bar menu will behave correctly when these system-level events occur.
There you have it! By following these steps, you can successfully create a MacOS native status bar menu using Flutter Desktop. Remember, the status bar can add a nice touch to your application’s user interface, providing easy access to common functions or settings, so take some time to design it well!