You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

iOS中如何实现类似控制中心/通知中心的可适配内容尺寸的模糊背景效果

iOS中如何实现类似控制中心/通知中心的可适配内容尺寸的模糊背景效果

我完全懂你想要的效果——就是像控制中心弹出的面板那样,背景能适度模糊下方内容但又不会过度,而且背景大小刚好贴合自己的内容,不是全屏糊一片对吧?之前你试的代码问题出在几个地方,我给你拆解下正确的实现方式,优先用系统原生方案,性能和适配都拉满:

一、系统原生Material方案(推荐,iOS 14+)

系统提供的Material系列背景是专门做这种模糊半透明效果的,完全适配系统明暗模式,而且是硬件加速的,性能拉满。之前你踩的坑是用了占满全屏的Rectangle,还错误叠加了blur修饰符,现在改成让背景跟着内容尺寸走:

代码示例

ZStack {
    // 这里放你的页面底层内容,比如原有的视图、背景色等
    Color.orange.overlay(Text("底层页面内容").font(.title))
    
    // 包裹你自己内容的容器(用VStack/HStack,尺寸由内部内容决定)
    VStack(spacing: 20) {
        Text("这是我的面板标题")
            .font(.headline)
        Text("面板里的内容1")
        Text("面板里的内容2")
        Button("点击测试按钮") {}
            .buttonStyle(.borderedProminent)
    }
    .padding(.horizontal, 30)
    .padding(.vertical, 25)
    // 给内容容器加背景,自动匹配容器尺寸
    .background {
        // 用RoundedRectangle做背景形状(可以改圆角大小,符合系统风格)
        RoundedRectangle(cornerRadius: 18)
            // 选择模糊程度,从淡到浓有这些选项:
            // ultraThinMaterial < thinMaterial < regularMaterial < thickMaterial < extraThickMaterial
            // 嫌太模糊的话选ultraThinMaterial,和控制中心的淡模糊一致
            .fill(.ultraThinMaterial)
            // 如果要调整色调,可以叠加一层半透明颜色,比如浅色模式下加淡白,深色加淡黑
            // .overlay(RoundedRectangle(cornerRadius: 18).fill(Color.white.opacity(0.05)))
    }
}

关键说明

  • 我们给**内容容器(VStack)**加背景,而不是用全屏的Rectangle,这样背景会自动跟着内容的尺寸走,不会占满屏幕
  • Material本身已经包含了模糊和半透明效果,不需要额外加blur(radius:),否则会重复模糊导致效果过强
  • 可以通过选择不同的Material变体(比如ultraThinMaterial.light/.dark)来适配不同的明暗模式,或者用systemUltraThinMaterial让系统自动适配

二、自定义模糊效果(适配iOS 13+,或需要更精细控制)

如果觉得系统Material的模糊程度还是不符合你的需求,比如想要更淡或者更偏某一种色调,可以用UIVisualEffectView封装一个自定义的模糊视图,配合颜色叠加来调整:

第一步:封装自定义BlurView

struct BlurView: UIViewRepresentable {
    // 可以自定义模糊风格,对应UIKit的UIBlurEffect.Style
    var style: UIBlurEffect.Style = .systemUltraThinMaterial
    
    func makeUIView(context: Context) -> UIVisualEffectView {
        let blurEffect = UIBlurEffect(style: style)
        let blurView = UIVisualEffectView(effect: blurEffect)
        return blurView
    }
    
    func updateUIView(_ uiView: UIVisualEffectView, context: Context) {
        uiView.effect = UIBlurEffect(style: style)
    }
}

第二步:使用自定义BlurView

ZStack {
    // 底层内容不变
    Color.purple.overlay(Text("底层页面内容").font(.title))
    
    // 内容容器
    VStack(spacing: 20) {
        Text("自定义模糊面板")
            .font(.headline)
        Text("自定义模糊效果的内容")
        Button("测试按钮") {}
    }
    .padding(25)
    .background {
        RoundedRectangle(cornerRadius: 16)
            // 用自定义BlurView作为背景
            .background(BlurView(style: .systemUltraThinMaterial))
            // 叠加一层半透明颜色,调整模糊的色调和深浅
            .overlay(RoundedRectangle(cornerRadius: 16).fill(Color.black.opacity(0.03)))
    }
}

关键说明

  • UIBlurEffect.Style有和SwiftUI Material对应的选项,比如.systemUltraThinMaterial对应ultraThinMaterial
  • 通过叠加不同透明度的颜色,可以精准控制模糊背景的色调和深浅,比如加一层淡白色会让模糊更偏亮,淡黑色则偏暗

最后纠正你之前代码的问题

你之前写的Rectangle.init().background(.thinMaterial).blur(radius: 20)有三个核心问题:

  1. Rectangle默认会填充整个父视图(你的ZStack),所以背景会全屏,不会贴合内容
  2. .background(.thinMaterial)是给Rectangle加背景色,而不是用Material作为填充,逻辑搞反了
  3. .blur(radius:20)是模糊Rectangle本身,而不是模糊它下方的内容,完全达不到你要的效果

按照上面的两种方案,你就能轻松实现控制中心那种贴合内容、模糊适度的面板背景啦,有问题再问我!

火山引擎 最新活动