桌面端差异化 (Desktop)
Compose for Desktop 赋予了我们在 PC (Windows/macOS/Linux) 上构建原生应用的能力。与移动端不同,桌面端有鼠标、键盘快捷键和多窗口系统。
1. 窗口管理 (Window)
桌面应用的入口是 Window Composable,而不是 Activity。
基础窗口
kotlin
fun main() = application {
Window(
onCloseRequest = ::exitApplication,
title = "我的桌面应用",
state = rememberWindowState(width = 800.dp, height = 600.dp),
icon = painterResource("icon.png") // 设置任务栏图标
) {
App()
}
}无边框窗口 (Undecorated)
用于自定义标题栏或异形窗口。
kotlin
Window(
onCloseRequest = ::exitApplication,
undecorated = true, // 去掉系统标题栏
transparent = true // 支持透明背景
) {
Surface(
shape = RoundedCornerShape(16.dp), // 圆角窗口
color = MaterialTheme.colorScheme.surface
) {
// 自定义标题栏区域,支持拖拽窗口
WindowDraggableArea {
Box(Modifier.fillMaxWidth().height(40.dp).background(Color.Gray)) {
Text("自定义标题", Modifier.align(Alignment.Center))
}
}
// 内容...
}
}2. 鼠标交互
移动端只有触摸,而桌面端有鼠标悬停、右键等操作。
悬停 (Hover) & 移入移出
kotlin
@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun HoverButton() {
var isHovered by remember { mutableStateOf(false) }
Box(
modifier = Modifier
.size(100.dp)
.background(if (isHovered) Color.Blue else Color.Gray)
.onPointerEvent(PointerEventType.Enter) { isHovered = true }
.onPointerEvent(PointerEventType.Exit) { isHovered = false }
// 改变鼠标指针样式 (变成小手)
.pointerHoverIcon(PointerIcon.Hand)
)
}右键菜单 (Context Menu)
Compose Desktop 提供了原生的 Swing 风格右键菜单,也可以自定义。
kotlin
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun RightClickArea() {
Box(
modifier = Modifier.size(200.dp).background(Color.LightGray)
) {
// 自动处理右键点击的区域
ContextMenuArea(
items = {
ContextMenuItem("复制") { /* Copy */ }
ContextMenuItem("粘贴") { /* Paste */ }
}
) {
Text("在此处右键")
}
}
}3. 键盘与快捷键
桌面应用重度依赖键盘操作。
kotlin
Window(
onCloseRequest = ::exitApplication,
// 监听全局键盘事件
onKeyEvent = { keyEvent ->
if (keyEvent.key == Key.Escape) {
// 按 ESC 关闭窗口
exitApplication()
true
} else false
}
) {
// ...
}4. 系统菜单栏 (MenuBar)
macOS 顶部的菜单栏或 Windows 窗口顶部的菜单。
kotlin
Window(...) {
MenuBar {
Menu("文件") {
Item("新建", onClick = { }, shortcut = KeyShortcut(Key.N, meta = true))
Item("打开", onClick = { }, shortcut = KeyShortcut(Key.O, meta = true))
Separator()
Item("退出", onClick = ::exitApplication)
}
Menu("帮助") {
Item("关于", onClick = { })
}
}
App()
}5. 系统托盘 (Tray)
让应用最小化到系统托盘区。
kotlin
fun main() = application {
// 托盘图标
Tray(
icon = painterResource("tray_icon.png"),
menu = {
Item("显示主窗口", onClick = { /* open window */ })
Item("退出", onClick = ::exitApplication)
}
)
// ... Window
}