如何自定义SwiftUI的Menu按钮?实现类iMessage菜单效果
在SwiftUI中实现iMessage风格的“更多”弹出菜单
我想实现iMessage中点击“更多”按钮后弹出的特定样式菜单(如下方目标效果所示),尝试使用ControlGroup和自定义ControlGroupStyle但没能达到预期效果,希望得到解决方法。
我尝试的代码
struct CustomControlGroupStyle: ControlGroupStyle { func makeBody(configuration: Configuration) -> some View { HStack { configuration.content } Divider() } } ControlGroup { Button { } label: { HStack { Image("ProfileImage") Text("Name") } } }.controlGroupStyle(CustomControlGroupStyle())
当前效果

目标效果

解决方案
ControlGroup更适合紧凑的内联控件组,要实现iMessage这种弹出式菜单,应该使用Menu组件配合自定义样式来实现,以下是完整实现代码:
// 自定义菜单样式,匹配iMessage视觉风格 struct iMessageMenuStyle: MenuStyle { func makeBody(configuration: Configuration) -> some View { Menu(configuration) .menuStyle(.borderlessButton) .presentationDetents([.height(220)]) // 根据选项数量调整高度 .presentationCornerRadius(16) } } // 统一菜单选项的布局样式 struct MenuOptionView: View { let icon: String let title: String let action: () -> Void var body: some View { Button(action: action) { HStack(spacing: 16) { Image(systemName: icon) .font(.title) .frame(width: 32) Text(title) .font(.system(size: 16)) Spacer() } .padding(.vertical, 12) .padding(.horizontal, 16) } } } // 使用示例 struct ContentView: View { var body: some View { VStack { // 触发菜单的“更多”按钮 Menu { MenuOptionView(icon: "person", title: "联系人", action: {}) Divider() MenuOptionView(icon: "photo", title: "照片", action: {}) MenuOptionView(icon: "camera", title: "拍照", action: {}) Divider() MenuOptionView(icon: "mic", title: "语音备忘录", action: {}) } label: { Image(systemName: "ellipsis.circle") .font(.title) } .menuStyle(iMessageMenuStyle()) } .padding() } }
实现说明
- 自定义
MenuStyle:设置菜单为无边框按钮样式,固定弹出高度并添加圆角,贴近iMessage的弹出效果。 MenuOptionView:统一每个选项的图标、文字布局,保证点击区域覆盖整行,交互更自然。- 分组分隔:通过
Divider将不同功能的选项分组,和iMessage菜单的结构保持一致。
内容的提问来源于stack exchange,提问作者Jacobino
相关产品推荐
相关产品推荐

