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

SwiftUI实现自定义宽度圆角矩形左右遮罩(保留圆角且不影响点击)

SwiftUI 实现带自定义左右遮罩且保留圆角的视图

你遇到的问题本质是用overlay添加的遮罩是直角矩形,覆盖了圆角矩形的边角区域,导致原本的圆角被遮挡。下面提供几种简单可行的实现方式,同时保证手势识别不受影响:

方案一:整体裁剪法(最简洁)

通过ZStack组合主体和遮罩,最后用clipShape统一裁剪成圆角,遮罩超出圆角的部分会被自动切掉,同时用contentShape确保整个圆角区域都能响应手势:

struct MaskedRoundedView: View {
    @State private var leftMaskWidth: CGFloat = 50
    @State private var rightMaskWidth: CGFloat = 50
    private let cornerRadius: CGFloat = 20
    private let viewSize = CGSize(width: 300, height: 100)

    var body: some View {
        ZStack(alignment: .leading) {
            // 橙色圆角主体
            RoundedRectangle(cornerRadius: cornerRadius)
                .fill(.orange)

            // 左侧白色遮罩
            Color.white
                .frame(width: leftMaskWidth)

            // 右侧白色遮罩
            Color.white
                .frame(width: rightMaskWidth)
                .alignmentGuide(.trailing) { $0[.trailing] }
        }
        .frame(size: viewSize)
        // 统一裁剪为圆角,遮罩超出边角的部分会被剪掉
        .clipShape(RoundedRectangle(cornerRadius: cornerRadius))
        // 确保整个圆角区域都能响应点击/手势
        .contentShape(RoundedRectangle(cornerRadius: cornerRadius))
        // 测试手势
        .onTapGesture {
            print("整个视图区域都能响应点击")
        }
    }
}

// 扩展简化frame写法
extension View {
    func frame(size: CGSize) -> some View {
        self.frame(width: size.width, height: size.height)
    }
}

方案二:背景覆盖法

用背景色作为遮罩,只显示中间的橙色圆角区域,视觉效果和遮罩一致,同时天然保留圆角:

struct MaskedRoundedView: View {
    @State private var leftMaskWidth: CGFloat = 50
    @State private var rightMaskWidth: CGFloat = 50
    private let cornerRadius: CGFloat = 20
    private let totalWidth: CGFloat = 300
    private let height: CGFloat = 100

    var body: some View {
        ZStack {
            // 白色背景(替代遮罩)
            RoundedRectangle(cornerRadius: cornerRadius)
                .fill(.white)

            // 橙色主体,只显示中间未被遮罩的部分
            RoundedRectangle(cornerRadius: cornerRadius)
                .fill(.orange)
                .frame(width: totalWidth - leftMaskWidth - rightMaskWidth, height: height)
                .offset(x: leftMaskWidth)
        }
        .frame(width: totalWidth, height: height)
        .contentShape(RoundedRectangle(cornerRadius: cornerRadius))
        .onTapGesture {
            print("点击有效")
        }
    }
}

方案三:遮罩匹配圆角法(精确控制遮罩圆角)

如果需要遮罩本身也带对应边角的圆角,可以单独给遮罩做裁剪,确保只覆盖需要的区域,同时设置allowsHitTesting(false)让遮罩不拦截手势:

struct MaskedRoundedView: View {
    @State private var leftMaskWidth: CGFloat = 50
    @State private var rightMaskWidth: CGFloat = 50
    private let cornerRadius: CGFloat = 20
    private let viewSize = CGSize(width: 300, height: 100)

    var body: some View {
        RoundedRectangle(cornerRadius: cornerRadius)
            .fill(.orange)
            .frame(size: viewSize)
            .overlay(alignment: .leading) {
                // 左侧遮罩:只保留左上角和左下角的圆角
                RoundedRectangle(cornerRadius: cornerRadius)
                    .fill(.white)
                    .frame(width: leftMaskWidth)
                    .clipShape(
                        RoundedRectangle(cornerRadius: cornerRadius)
                            .offset(x: leftMaskWidth - cornerRadius)
                            .frame(width: leftMaskWidth + cornerRadius)
                    )
                    .allowsHitTesting(false)
            }
            .overlay(alignment: .trailing) {
                // 右侧遮罩:只保留右上角和右下角的圆角
                RoundedRectangle(cornerRadius: cornerRadius)
                    .fill(.white)
                    .frame(width: rightMaskWidth)
                    .clipShape(
                        RoundedRectangle(cornerRadius: cornerRadius)
                            .offset(x: -(rightMaskWidth - cornerRadius))
                            .frame(width: rightMaskWidth + cornerRadius)
                    )
                    .allowsHitTesting(false)
            }
            .onTapGesture {
                print("点击有效")
            }
    }
}

以上三种方案都能保留圆角矩形的原始形状,同时不会影响手势识别。其中方案一和方案二代码更简洁,推荐优先使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 13:43:11