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
相关产品推荐
相关产品推荐

