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

SwiftUI:使用.blur致导航标题与安全区域重叠(iOS17已修复)

解决SwiftUI后台切换时导航标题与顶部安全区域重叠的问题

编辑说明:该问题在iOS 17中已修复

我希望应用处于后台时添加模糊效果,因此在TestApp.swift中编写了如下代码:

import SwiftUI

@main
struct TestApp: App {
    @Environment(\.scenePhase) var scenePhase
    
    var body: some Scene {
        WindowGroup {
            ContentView()
                .blur(radius: scenePhase != .active ? 200 : 0)
        }
    }
}

在ContentView.swift中,我实现了一个TabView,每个标签页对应一个NavigationStack,代码如下:

import SwiftUI

struct ContentView: View {
    var body: some View {
        TabView {
            NavigationStack {
                List {
                    Text("(a)")
                    Text("(b)")
                    Text("(c)")
                }
                .navigationTitle("AAA")
                .navigationBarTitleDisplayMode(.inline)
            }
            .tabItem{Text("a") }
            .tag("a")
            NavigationStack {
                List {
                    Text("b")
                    Text("b")
                    Text("b")
                }
                .navigationTitle("BBBB")
                .navigationBarTitleDisplayMode(.inline)
            }
            .tabItem{Text("b")}
            .tag("b")
        }
    }
}

但在应用前后台切换时,导航标题会与顶部安全区域重叠,只有点击安全区域才能恢复正常。


解决方案

问题根源在于直接在App层级给ContentView添加blur修饰符,干扰了SwiftUI对导航栏和安全区域的布局计算。可以通过以下两种方式修复:

方案一:将模糊修饰符移到ContentView内部

把blur作用在TabView上,避免影响App层级的布局逻辑:

import SwiftUI

struct ContentView: View {
    @Environment(\.scenePhase) var scenePhase
    
    var body: some View {
        TabView {
            NavigationStack {
                List {
                    Text("(a)")
                    Text("(b)")
                    Text("(c)")
                }
                .navigationTitle("AAA")
                .navigationBarTitleDisplayMode(.inline)
            }
            .tabItem{Text("a") }
            .tag("a")
            
            NavigationStack {
                List {
                    Text("b")
                    Text("b")
                    Text("b")
                }
                .navigationTitle("BBBB")
                .navigationBarTitleDisplayMode(.inline)
            }
            .tabItem{Text("b")}
            .tag("b")
        }
        .blur(radius: scenePhase != .active ? 200 : 0)
    }
}

方案二:通过ZStack给背景添加模糊

不在ContentView本身添加模糊,而是用ZStack给背景层添加模糊效果,保证内容层的布局不受影响:

import SwiftUI

@main
struct TestApp: App {
    @Environment(\.scenePhase) var scenePhase
    
    var body: some Scene {
        WindowGroup {
            ZStack {
                // 给背景层添加模糊
                Color.clear
                    .blur(radius: scenePhase != .active ? 200 : 0)
                ContentView()
            }
        }
    }
}

两种方案都能避免模糊修饰符干扰导航栏的布局计算,解决前后台切换时的标题重叠问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 04:00:42