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

如何为任意SwiftUI View添加内阴影?解决非Shape视图实现难题

为任意SwiftUI View实现内阴影效果

SwiftUI中,Shape子类(如RoundedRectangle)可以直接通过.fill(.shadow(.inner(...)))实现内阴影,但对于Text这类非Shape视图,这种方法并不适用。下面提供一个通用方案,可给任意SwiftUI View添加内阴影:

自定义ViewModifier实现通用内阴影

通过自定义ViewModifier,利用视图复制、遮罩和混合模式,模拟出内阴影效果,且不会遮挡原视图内容:

struct InnerShadowModifier: ViewModifier {
    let color: Color
    let radius: CGFloat
    let offsetX: CGFloat
    let offsetY: CGFloat
    
    // 简化初始化,默认水平偏移为0
    init(color: Color, radius: CGFloat, offsetX: CGFloat = 0, offsetY: CGFloat) {
        self.color = color
        self.radius = radius
        self.offsetX = offsetX
        self.offsetY = offsetY
    }
    
    func body(content: Content) -> some View {
        content
            .overlay(
                content
                    .offset(x: offsetX, y: offsetY)
                    .shadow(color: color, radius: radius)
                    .mask(content)
                    .blendMode(.destinationOut)
            )
            .compositingGroup()
    }
}

// 给View添加扩展,方便链式调用
extension View {
    func innerShadow(color: Color, radius: CGFloat, offsetX: CGFloat = 0, offsetY: CGFloat) -> some View {
        self.modifier(InnerShadowModifier(color: color, radius: radius, offsetX: offsetX, offsetY: offsetY))
    }
}

使用示例

给Text添加内阴影+外投影

#Preview {
    VStack {
        Text("Hello Inner Shadow")
            .font(.largeTitle)
            .fontWeight(.bold)
            .background(.blue)
            .frame(width: .infinity, height: 100)
            .innerShadow(color: .white, radius: 1, offsetY: -1)
            .shadow(radius: 10) // 叠加外投影
        Spacer()
    }
    .background(.yellow)
    .padding()
}

给Shape复用该方法

效果和原生.fill(.shadow(.inner(...)))一致,且统一调用逻辑:

#Preview {
    VStack {
        RoundedRectangle(cornerRadius: 10)
            .fill(.blue)
            .frame(width: .infinity, height: 100)
            .innerShadow(color: .white, radius: 1, offsetY: -1)
            .shadow(radius: 10)
        Spacer()
    }
    .background(.yellow)
    .padding()
}

方案原理说明

  1. 复制原视图并偏移:让阴影出现在目标方向(比如向上偏移则顶部生成内阴影)
  2. 用原视图作为遮罩:限制阴影只在原视图的范围内显示
  3. .blendMode(.destinationOut):让阴影区域“挖掉”原视图对应位置的像素,模拟内阴影的凹陷效果
  4. .compositingGroup():确保混合模式和阴影效果正确作用于整个视图组,避免影响外部视图

这个方案的核心优势是不依赖固定Shape,适用于任意SwiftUI View(包括Text、Image、容器视图等),且不会遮挡原视图的内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 14:35:55