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

如何修改SwiftUI中redacted修饰符的shimmer闪烁效果颜色

SwiftUI redacted 闪烁效果透出原有底色解决方案

问题原因

SwiftUI 原生的 .redacted(.placeholder) 修饰符只会修改无自定义背景的视图的占位样式,已经设置了自定义 background 底色的视图会保留原有颜色,不会被占位样式覆盖,因此会出现底色透出的问题。

解决方案

方案1:父容器叠加蒙版(快速修复,无需修改子视图)

直接给添加了redacted的父容器叠加半透灰色蒙版,强制覆盖所有子视图的原有底色:

VStack{
  TopView()
  HomeView()
}
.redacted(.placeholder)
// 新增两行代码
.overlay(.gray.opacity(0.4)) // 透明度可根据系统默认占位灰色调整
.allowsHitTesting(false) // 加载状态下禁止交互
  • 适用场景:临时快速修复,子视图逻辑复杂不想修改时使用

方案2:子视图条件清空背景(保留系统原生动画)

通过加载状态参数控制,让所有带自定义底色的子视图在加载状态下清空原有背景:

  1. 先定义加载状态变量
@State var isLoading: Bool = true
  1. 所有带自定义背景的子视图增加背景条件判断
// 子视图原有示例代码
Text("自定义内容")
  .background(isLoading ? .clear : Color.customRed) // 加载状态下清空背景
  1. 父容器控制redacted生效条件
VStack{
  TopView(isLoading: isLoading)
  HomeView(isLoading: isLoading)
}
.redacted(reason: isLoading ? .placeholder : [])
  • 适用场景:需要完全保留系统原生占位闪烁效果,性能最优

方案3:自定义统一Shimmer修饰符(效果完全可控)

如果不需要用系统原生redacted,自定义Shimmer修饰符可以彻底解决底色透出问题,还支持自定义动画参数:

// 自定义Shimmer修饰符
struct ShimmerModifier: ViewModifier {
    @State private var offset: CGFloat = -1
    let isLoading: Bool
    
    func body(content: Content) -> some View {
        if isLoading {
            content
                .overlay(
                    GeometryReader { geo in
                        LinearGradient(
                            gradient: Gradient(colors: [.gray.opacity(0.2), .gray.opacity(0.5), .gray.opacity(0.2)]),
                            startPoint: .leading,
                            endPoint: .trailing
                        )
                        .frame(width: geo.size.width * 2)
                        .offset(x: geo.size.width * offset)
                        .animation(.linear(duration: 1.5).repeatForever(autoreverses: false), value: offset)
                    }
                )
                .mask(content)
                .onAppear {
                    offset = 1
                }
        } else {
            content
        }
    }
}

extension View {
    func shimmer(_ isLoading: Bool) -> some View {
        self.modifier(ShimmerModifier(isLoading: isLoading))
    }
}

使用方式:

VStack{
  TopView()
  HomeView()
}
.shimmer(isLoading)
  • 适用场景:需要统一所有视图的加载闪烁效果,或需要定制动画样式时使用

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 11:24:06