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
相关产品推荐
相关产品推荐

