You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI自定义导航栏气泡式菜单实现方案咨询

实现苹果Reminders风格的气泡式Toolbar菜单

要复刻Reminders APP中点击按钮弹出的气泡样式菜单,有两种可行方案,分别适配不同的自定义需求:

方案1:纯SwiftUI自定义气泡菜单

适合需要完全控制菜单样式的场景,通过Popover手动构建菜单内容:

import SwiftUI

struct ContentView: View {
    @State private var showPopover = false
    
    var body: some View {
        NavigationView {
            Text("主内容视图")
                .navigationTitle("标题")
                .toolbar {
                    ToolbarItem(placement: .topBarTrailing) {
                        Button {
                            showPopover.toggle()
                        } label: {
                            Label("更多", systemImage: "ellipsis")
                        }
                        // 设置气泡箭头指向按钮顶部,匹配Reminders样式
                        .popover(isPresented: $showPopover, arrowEdge: .top) {
                            VStack(spacing: 0) {
                                // 菜单选项1
                                Button {
                                    showPopover = false
                                    // 执行对应动作
                                } label: {
                                    HStack {
                                        Image(systemName: "list.bullet")
                                        Text("查看列表")
                                        Spacer()
                                    }
                                    .padding(.vertical, 12)
                                    .padding(.horizontal, 16)
                                    .frame(minWidth: 200)
                                }
                                
                                Divider()
                                
                                // 菜单选项2
                                Button {
                                    showPopover = false
                                    // 执行对应动作
                                } label: {
                                    HStack {
                                        Image(systemName: "plus")
                                        Text("新建列表")
                                        Spacer()
                                    }
                                    .padding(.vertical, 12)
                                    .padding(.horizontal, 16)
                                    .frame(minWidth: 200)
                                }
                                
                                Divider()
                                
                                // 菜单选项3
                                Button {
                                    showPopover = false
                                    // 执行对应动作
                                } label: {
                                    HStack {
                                        Image(systemName: "trash")
                                        Text("删除列表")
                                        Spacer()
                                    }
                                    .padding(.vertical, 12)
                                    .padding(.horizontal, 16)
                                    .frame(minWidth: 200)
                                }
                            }
                            .background(Color(.systemBackground))
                            .cornerRadius(12)
                            .shadow(color: .black.opacity(0.1), radius: 8, x: 0, y: 2)
                        }
                    }
                }
        }
    }
}

方案2:UIKit包装原生系统菜单

适合追求完全原生样式和交互的场景,利用UIKit的UIMenu实现:

import SwiftUI
import UIKit

struct SystemPopoverMenu: UIViewRepresentable {
    let menuOptions: [(title: String, icon: String, action: () -> Void)]
    
    func makeUIView(context: Context) -> UIButton {
        let button = UIButton(type: .system)
        button.setImage(UIImage(systemName: "ellipsis"), for: .normal)
        button.setTitle("更多", for: .normal)
        button.showsMenuAsPrimaryAction = true
        
        // 构建原生菜单
        let menu = UIMenu(children: menuOptions.map { option in
            UIAction(title: option.title, image: UIImage(systemName: option.icon)) { _ in
                option.action()
            }
        })
        
        button.menu = menu
        // 设置菜单为气泡样式
        button.menu?.presentationStyle = .popover
        button.menu?.preferredElementSize = .medium
        
        return button
    }
    
    func updateUIView(_ uiView: UIButton, context: Context) {}
}

// 使用示例
struct ContentView: View {
    var body: some View {
        NavigationView {
            Text("主内容视图")
                .navigationTitle("标题")
                .toolbar {
                    ToolbarItem(placement: .topBarTrailing) {
                        SystemPopoverMenu(menuOptions: [
                            (title: "查看列表", icon: "list.bullet", action: { /* 执行动作 */ }),
                            (title: "新建列表", icon: "plus", action: { /* 执行动作 */ }),
                            (title: "删除列表", icon: "trash", action: { /* 执行动作 */ })
                        ])
                    }
                }
        }
    }
}

说明

  • 方案1可以自由调整菜单的颜色、间距、阴影等细节,完全自定义外观。
  • 方案2直接复用系统原生菜单的样式和交互逻辑,包括点击高亮、动画效果,和Reminders的菜单表现完全一致。

内容的提问来源于stack exchange,提问作者ScoobyDooku

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 03:16:07