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

如何自定义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()
    }
}

实现说明

  1. 自定义MenuStyle:设置菜单为无边框按钮样式,固定弹出高度并添加圆角,贴近iMessage的弹出效果。
  2. MenuOptionView:统一每个选项的图标、文字布局,保证点击区域覆盖整行,交互更自然。
  3. 分组分隔:通过Divider将不同功能的选项分组,和iMessage菜单的结构保持一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 07:27:31