ContentView (SwiftUI) 的背景图像不是子视图,但具有正确的滚动行为

Posted

技术标签:

【中文标题】ContentView (SwiftUI) 的背景图像不是子视图,但具有正确的滚动行为【英文标题】:Background image for ContentView (SwiftUI) not subviews but with proper scrolling behavior 【发布时间】:2019-11-04 21:16:30 【问题描述】:

我们如何获取 ContentView 的背景图片而不是其子视图,并保留可滚动内容在 NavBar 下消失的行为?

我发现,如果我将背景作为修饰符添加到 List 或 ScrollView,它不会更改子视图(例如 DetailView)的背景,但可滚动内容不再消失在导航栏下,并且导航栏标题保持原位(见图#2)。但是,如果我修改 NavigationView,它会恢复可滚动内容在导航栏下消失的行为(参见图 #3),但它也改变了所有子视图的背景(参见图 #4)

我尝试了一个带有 Image("MoonPhoto") 的 ZStack,然后是 List

但主要是我尝试了这个 ViewModifier 结构的不同位置:

struct BackgroundImage: ViewModifier 
    func body(content: Content) -> some View 
        content
            .opacity(0.8)
            .background(Image("history-in-hd-e5eDHbmHprg-unsplash")
            .resizable()
            .scaledToFill())
    

这里是ContentView的主体:

     var body: some View 
        NavigationView 
            List(missions)  mission in
                NavigationLink(destination: MissionView(mission: mission, astronauts: self.astronauts))
                
                    Image(mission.image)
                        .resizable()
                        .scaledToFit()
                        .frame(width: 50, height: 50)

                    VStack(alignment: .leading) 
                        Text(mission.displayName)
                            .font(.headline)
                        Text(self.showCrew ? self.crewList(mission: mission) : mission.formattedLaunchDate)
                    
                
                .navigationBarTitle("Moonshot")
            
            .navigationBarTitle("Moonshot")
            .navigationBarItems(leading:
                Button(self.showCrew ? "Show Launch date" : "Show crew") 
                    self.showCrew.toggle()
                
            )
            .modifier(BackgroundImage()) //Modifying List
         //If you move the above modifier here, the image shows an all subviews too
    

【问题讨论】:

我现在无法回答您的问题。但我建议您在进一步搜索之前阅读以下内容:***.com/questions/57128547/…。 如果你能看看就好了。我尝试了与您链接的文章不同的方法,但它们似乎不是答案。甚至他们的一个答案都表明需要导航栏 - 否则滚动内容会超出安全区域并且看起来不太好。 【参考方案1】:

我观察到的主要问题是关于 navigationBarTitle 修饰符的 .large DisplayMode。我找到了适合我的解决方案,但它仍然是一种解决方法。无论如何,您可以将其视为临时解决方案。

主要思想是将 List 包装在 VStack 中并使用 .inline 显示模式。希望这会有所帮助。

如下所示(也适用于深色模式)

import SwiftUI

struct BackgroundImage: ViewModifier 
    func body(content: Content) -> some View 
        content
            .opacity(0.8)
            .background(Image("history-in-hd-e5eDHbmHprg-unsplash")
            .resizable()
            .scaledToFill())
    



struct ContentView: View 
    var body: some View 
        NavigationView 
            VStack 
                List (1...20, id: \.self)  value in
                    NavigationLink(destination: Text("Details \(value)")) 
                        Text("\(value)")
                    
                
            
            .modifier(BackgroundImage())
            .navigationBarTitle("Title", displayMode: .inline)
        
    


struct ContentView_Previews: PreviewProvider 
    static var previews: some View 
        ContentView()
    

【讨论】:

这仅适用于一个小的(但我可以接受)权衡:应用标题开始内联,而不是在滚动时动画到该位置。

以上是关于ContentView (SwiftUI) 的背景图像不是子视图,但具有正确的滚动行为的主要内容,如果未能解决你的问题,请参考以下文章

AppDelegate 和 ContentView() 之间的 SwiftUI 通信

在 SwiftUI 开始渲染 ContentView 之前,我们如何从 Views 中独立运行一些逻辑?

SwiftUI - 从 Swift 类启动的可观察对象不会更新 ContentView() 上的 @ObservedObject

SwiftUI 检查 URL 是不是可达并自动切换到 ContentView

SwiftUI - 预览时未知的预览提供程序“ContentView_Previews_”。发生在一个全新的项目中

SwiftUI SceneDelegate - contentView 在调用中缺少参数“索引”的参数