Apps ancrées au tray
TrayApp ancre une fenêtre popup Compose à une icône du tray système pour construire des apps menu bar en Kotlin.
TrayApp ancre une fenêtre Compose complète à une icône du tray système : vous cliquez gauche sur
l'icône et la fenêtre s'ouvre à côté, vous cliquez ailleurs et elle se ferme. C'est le pattern menu
bar app utilisé par des outils comme Bartender, iStat Menus et Hidden Bar.
Expérimental
TrayApp est en alpha et l'API peut changer. Activez-le avec @OptIn(ExperimentalTrayAppApi::class).
Ajouter la dépendance
TrayApp est inclus dans composenativetray. Si cette dépendance est sur
votre classpath, aucun artefact supplémentaire n'est nécessaire.
Créer une tray app
Passez une icône, un tooltip, une taille de fenêtre et le contenu Compose à afficher dans la popup :
@OptIn(ExperimentalTrayAppApi::class)
fun main() = application {
TrayApp(
icon = Icons.Default.Dashboard,
tooltip = "Quick dashboard",
windowSize = DpSize(300.dp, 400.dp),
) {
Column(Modifier.fillMaxSize().padding(16.dp)) {
Text("Dashboard", style = MaterialTheme.typography.h6)
Spacer(Modifier.height(8.dp))
Text("CPU: 42%")
Text("RAM: 8.2 GB")
}
}
}Fonctionnement
TrayApp combine une icône tray et une fenêtre Compose transparente, sans décoration et toujours
au-dessus. La bibliothèque suit la position de l'icône à l'écran et place la fenêtre à côté avec
l'offset adapté à chaque système d'exploitation.
Le clic-en-dehors-pour-fermer est branché sur l'événement de perte de focus de l'OS : la popup se ferme comme les fenêtres menu bar natives de chaque bureau.
Piloter la visibilité et la taille avec l'état
Conservez un TrayAppState pour afficher, masquer, redimensionner ou changer le mode de dismiss
depuis votre propre code :
@OptIn(ExperimentalTrayAppApi::class)
fun main() = application {
val state = rememberTrayAppState(
initialWindowSize = DpSize(350.dp, 500.dp),
initiallyVisible = false,
initialDismissMode = TrayWindowDismissMode.AUTO,
)
TrayApp(
icon = Icons.Default.Dashboard,
tooltip = "Dashboard",
state = state,
) {
Column {
Text("Dashboard")
Button(onClick = { state.hide() }) { Text("Fermer") }
Button(onClick = { state.setWindowSize(500.dp, 600.dp) }) { Text("Redimensionner") }
}
}
}Ajouter un menu contextuel
Le clic gauche ouvre la popup ; le clic droit ouvre un menu classique :
@OptIn(ExperimentalTrayAppApi::class)
fun main() = application {
TrayApp(
icon = Icons.Default.Dashboard,
tooltip = "Dashboard",
menu = {
Item(label = "Réglages") { openSettings() }
Divider()
Item(label = "Quitter") { exitProcess(0) }
},
) {
Text("Contenu de la popup")
}
}Masquer l'icône du Dock sur macOS
Une tray app n'a généralement pas besoin d'icône dans le Dock. Sur macOS, mettez LSUIElement = true
dans l'Info.plist de l'app. Le plugin Gradle Nucleus expose macOS.infoPlist.extraKeysRawXml
pour cela :
nucleus {
application {
nativeDistributions {
macOS {
infoPlist {
extraKeysRawXml = """
<key>LSUIElement</key>
<true/>
""".trimIndent()
}
}
}
}
}L'app tourne alors sans entrée dans le Dock ni barre de menus — seule l'icône du tray reste.
Référence de l'API
Options de fenêtre de TrayApp
| Paramètre | Défaut | Notes |
|---|---|---|
windowSize | DpSize(300.dp, 200.dp) | taille initiale |
visibleOnStart | false | affiche tout de suite |
enterTransition / exitTransition | défaut plateforme | animations |
transparent | true | fond transparent |
undecorated | true | sans cadre |
resizable | false | redimensionnement utilisateur |
horizontalOffset / verticalOffset | 0 / défaut plateforme | décalage depuis l'icône |
TrayAppState
| API | Description |
|---|---|
isVisible: StateFlow<Boolean> | visibilité courante |
show() / hide() / toggle() | contrôle impératif |
setWindowSize(size) | redimensionne à la volée |
setDismissMode(mode) | AUTO (clic dehors ferme) ou MANUAL |
onVisibilityChanged(cb) | observer les transitions |
Et ensuite
- System tray — l'API d'icône tray sur laquelle repose
TrayApp. - DSL menu du tray — construire le menu du clic droit.
- Single instance — un re-launch depuis le
.appré-affiche la popup au lieu de démarrer un second process.
DSL menu du tray
Construisez le menu contextuel du tray depuis Kotlin avec des items, des cases à cocher, des sous-menus, des séparateurs et du contenu conditionnel.
Raccourcis globaux
Enregistrez des raccourcis clavier au niveau de l'OS qui se déclenchent même quand votre application n'a pas le focus.