PAYATHON 2026

SwiftUI 如何按下圆形按钮打开设备选择菜单?

数据小许

结论

按下自定义圆形按钮显示设备菜单时,可以用 Menu 替换 .menu 样式的 Picker,并将圆形图标视图设为 Menu 的 label。选中菜单项后,更新 selectedDeviceID;选择“Don’t record microphone”时,将它设为 nil。

现有的 DevicePickerButton 已经把自定义圆形视图用作 Picker 的标签。如果想用另一种自定义按钮打开菜单,可以改用 Menu。SwiftUI 没有公开接口可让普通 Button 直接触发 Picker 自带的菜单。

用 Menu 替换 Picker

下面的写法保留设备列表和不录制麦克风选项,并继续用 pickerLabel 设置菜单按钮的外观:

var body: some View {
    Menu {
        if !devices.isEmpty {
            Section("Devices") {
                ForEach(devices, id: \.uniqueID) { device in
                    Button {
                        selectedDeviceID = device.uniqueID
                    } label: {
                        Text(device.localizedName)
                    }
                }
            }
        }

        Section {
            Button("Don't record microphone") {
                selectedDeviceID = nil
            }
        }
    } label: {
        pickerLabel
    }
    .menuStyle(.borderlessButton)
}

pickerLabel 可以沿用现有实现,包括 Circle 背景、悬停状态、图标和阴影。视图也可以继续根据当前选择显示不同图标:

private var currentIcon: String {
    selectedDeviceID != nil ? icon : disabledIcon
}

选择设备后,selectedDeviceID 会更新。选择“Don’t record microphone”后,它会变为 nil,currentIcon 也会切换到 disabledIcon。

注意事项

Menu 会响应标签视图的点击并显示菜单,因此不需要再将它包在 Button 中。.borderlessButton 可以减少菜单控件额外的按钮外观。如果项目使用的 macOS 或 SwiftUI 版本不支持该样式,可以先移除这一行,再检查自定义标签的显示效果。

示例假设设备列表和 selectedDeviceID 的绑定已由现有视图提供。这里通过 Menu 创建自定义菜单入口,没有使用特定系统版本的额外菜单 API。

备注:内容仅供参考。