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

如何在SwiftUI(MacOS)中实现连体按钮效果?

macOS SwiftUI 连体相邻按钮实现方案(兼容10.15 / 11.x 版本)

实现逻辑

  • macOS 11+ 系统原生提供ControlGroup组件,默认自带和TextEdit一致的连体按钮样式,无需额外自定义
  • macOS 10.15 没有对应原生组件,通过自定义视图组合、手动控制圆角和边框的方式模拟效果

完整可运行代码

import SwiftUI

// 跨版本兼容连体按钮组容器
struct JoinedButtonGroup<Content: View>: View {
    let content: Content
    
    init(@ViewBuilder content: () -> Content) {
        self.content = content()
    }
    
    var body: some View {
        if #available(macOS 11.0, *) {
            ControlGroup {
                content
            }
            .controlGroupStyle(.automatic)
        } else {
            HStack(spacing: 0) {
                content
            }
            .overlay(
                RoundedRectangle(cornerRadius: 6)
                    .stroke(Color.secondary.opacity(0.3), lineWidth: 1)
            )
            .cornerRadius(6)
        }
    }
}

// 按钮样式扩展,适配连体效果
extension Button {
    func joinedButtonStyle(isFirst: Bool = false, isLast: Bool = false) -> some View {
        if #available(macOS 11.0, *) {
            return self
        } else {
            return self
                .buttonStyle(BorderlessButtonStyle())
                .padding(.horizontal, 12)
                .padding(.vertical, 6)
                .background(
                    Rectangle()
                        .fill(Color.clear)
                        .overlay(
                            Rectangle()
                                .fill(Color.secondary.opacity(0.3))
                                .frame(width: 1),
                            alignment: .trailing
                        )
                        .opacity(isLast ? 0 : 1)
                )
                .cornerRadius(6, corners: isFirst ? [.topLeft, .bottomLeft] : [])
                .cornerRadius(6, corners: isLast ? [.topRight, .bottomRight] : [])
        }
    }
}

// 辅助工具:指定圆角位置
extension View {
    func cornerRadius(_ radius: CGFloat, corners: RectCorner) -> some View {
        clipShape(RoundedCorner(radius: radius, corners: corners))
    }
}

struct RoundedCorner: Shape {
    var radius: CGFloat = .infinity
    var corners: RectCorner = .allCorners

    func path(in rect: CGRect) -> Path {
        let path = NSBezierPath(roundedRect: rect, byRoundingCorners: corners, cornerRadii: NSSize(width: radius, height: radius))
        return Path(path.cgPath)
    }
}

使用示例

struct ContentView: View {
    var body: some View {
        JoinedButtonGroup {
            Button("加粗") {
                // 业务逻辑
            }
            .joinedButtonStyle(isFirst: true)
            
            Button("斜体") {
                // 业务逻辑
            }
            .joinedButtonStyle()
            
            Button("下划线") {
                // 业务逻辑
            }
            .joinedButtonStyle(isLast: true)
        }
        .padding()
        .frame(width: 300, height: 150)
    }
}

样式调整说明

  • 可修改cornerRadius参数值匹配App的整体设计风格
  • 按钮内边距、分隔线颜色、边框宽度都可根据需求自定义调整
  • 11+版本可通过修改controlGroupStyle参数切换不同的原生连体样式

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 17:18:01