PAYATHON 2026

Apple 如何在以 SF Symbol 表示当前值的菜单中显示选中状态?

数据小许

结论

可以先采用 Menu 内嵌 Picker 的实现:菜单入口显示当前选项的 SF Symbol,菜单内用 Label 显示选项文字和图标,单选状态和系统 checkmark 由 Picker 管理,无需手动添加第二个 Image。

Apple 的官方示例展示了菜单内的 Picker,也有用 Label 为选项添加图标的代码。这可以作为实现参考,但不能据此认定 Apple 自家应用使用了相同代码。Apple 官方菜单示例

为什么不必手动放置 checkmark

选项图标表示选项的含义,checkmark 表示选择状态。使用 Picker(selection:) 后,系统会根据绑定值标记当前选项,不必把 checkmark 作为另一个图像放进菜单项的 label。

原问题中“每行只能显示一个图像”的观察,不足以说明菜单无法同时显示选项图标和选中标记。可以先用控件表达选择关系,再由系统呈现状态。

实现示例

以下示例包含两种显示方式。菜单入口只显示当前选项的图标,展开后显示各选项的文字和图标:

import SwiftUI

struct DisplayModeMenu: View {
    enum DisplayMode: String, CaseIterable, Hashable {
        case list = "列表"
        case grid = "网格"

        var systemImage: String {
            switch self {
            case .list:
                return "list.bullet"
            case .grid:
                return "square.grid.2x2"
            }
        }
    }

    @State private var selected: DisplayMode = .list

    var body: some View {
        Menu {
            Picker("显示方式", selection: $selected) {
                ForEach(DisplayMode.allCases, id: \.self) { mode in
                    Label(mode.rawValue, systemImage: mode.systemImage)
                        .tag(mode)
                }
            }
            .pickerStyle(.inline)
        } label: {
            Label(
                "显示方式:\(selected.rawValue)",
                systemImage: selected.systemImage
            )
            .labelStyle(.iconOnly)
        }
    }
}

代码中:

  • selection 和 .tag(mode) 使用相同类型,让 Picker 识别当前选项。
  • .pickerStyle(.inline) 让选项直接出现在外层菜单中。对菜单内部的 Picker 使用 .menu 会形成子菜单。Apple 的 menu 样式说明
  • .labelStyle(.iconOnly) 只应用于菜单入口,保留入口的文字语义;菜单内的选项仍使用各自的 Label。

图标位置与 Apple 应用实例

上述代码定义了选项的图标、文字和选择状态,但不能保证图标始终位于文字左侧。原生菜单的具体排列受平台、系统版本和上下文影响,应在目标 iOS 版本上确认显示效果。如果必须固定每个元素的位置,再考虑自定义弹出界面。

现有材料没有可核对的 Apple 应用截图或具体界面,因此无法可靠列举完全对应的自家应用实例。官方文档可以确认,在菜单中使用带图标的 Picker 选项是受支持的用法;实际产品的内部实现不能仅凭外观判断。

备注:内容仅供参考。