【问题标题】:Extra Space from the top of the screen屏幕顶部的额外空间
【发布时间】:2020-09-07 12:12:51
【问题描述】:

我正在尝试使用 SwiftUI 为我的屏幕设置背景图像。 我注意到屏幕顶部大约 10 像素处有某种插图,我不确定那是什么?以及如何从最顶部开始图像。

这是我的代码:


struct AppBackGround: ViewModifier {
    
    func body(content: Content) -> some View {
             ZStack {
                Image("background")
                    .resizable()

                    .edgesIgnoringSafeArea(.all)

                    .scaledToFill()
                    .frame(width: UIScreen.main.bounds.width,
                           height: UIScreen.main.bounds.height, alignment: .top)

//                    .clipped()

                    .border(Color.red, width: 1)
                    .Print(UIScreen.main.bounds.height)
                
                content
         }

             .background(Color.red)
    }
}

extension View {
    func withAppBackground() -> some View {
        self.modifier(AppBackGround())
    }
}

struct AppBackGround_Previews: PreviewProvider {
    static var previews: some View {
        Group {
            ZStack {
                Text("iphone 8 plus")
            }
            .withAppBackground()
            .colorScheme(.light).previewDevice("iPhone 8 Plus")
            
            ZStack {
                Text("iphone 11")
            }
            .withAppBackground()
            .colorScheme(.light).previewDevice("iPhone 11")
        }
    }
}


在下图中,您可以看到有一个红色边框围绕着图像的确切框架。您会注意到图像顶部和屏幕顶部之间有一个空间。

这也是原图,如果你想试试看。

【问题讨论】:

    标签: ios swift xcode swiftui


    【解决方案1】:

    我不能确切地说那个小空间是什么,但要修复它,您可以将 .edgesIgnoringSafeArea(.all)Image 移动到包含整个 ViewZStack

    struct AppBackGround: ViewModifier {
        
    
        func body(content: Content) -> some View {
                 ZStack {
                    Image("background")
                        .resizable()
    
                        // .edgesIgnoringSafeArea(.all)  // remove this
    
                        .scaledToFill()
                        .frame(width: UIScreen.main.bounds.width,
                               height: UIScreen.main.bounds.height, alignment: .top)
    
    //                    .clipped()
    
                        .border(Color.red, width: 1)
                        .Print(UIScreen.main.bounds.height)
                    
                    content
             }
    
                 .background(Color.red)
                 .edgesIgnoringSafeArea(.all)   // add this
        }
    }
    

    AppBackGround 可以通过将Image 设置为背景Color.redoverlay 来进一步简化。这允许删除frame,因为Color.red 将填满屏幕,因为.edgesIgnoringSafeArea(.all)

    struct AppBackGround: ViewModifier {
        
        func body(content: Content) -> some View {
             ZStack {
                Color.red
                    .overlay(
                        Image("background")
                            .resizable()
                            .scaledToFill()
                    )
                    .border(Color.red, width: 1)
                
                content
             }
             .edgesIgnoringSafeArea(.all)
        }
    }
    

    【讨论】:

    • 这确实有效!谢谢,但想知道为什么我们必须在这里使用叠加层,为什么不直接使用图像。
    • 如果直接使用图片,它将决定视图的大小。在宽图像的情况下,您最终会看到比屏幕宽得多的视图。通过让Color.red(或Rectangle())建立视图大小,.overlay() 不会改变它。然后将缩放图像以填充父视图建立的边界。这允许content 然后以手机屏幕大小的视图为中心。
    • 另一种方法是做你最初做的事情,给图像一个明确的框架。覆盖层对我来说看起来更整洁,但框架也很好用。您可以使用 GeometryReader 来确定框架的大小,而无需将其硬编码为 UIScreen.main.bounds,这与 SwiftUI 不太相似。
    • 我明白了,您的解决方案效果更好,无论是使用 GeometryReader 还是 UIScreen 的框架都没有按照问题中的说明工作。
    【解决方案2】:

    只需删除硬编码的帧,让图像动态填充所有可用区域

        Image("background")
            .resizable()
            .scaledToFill()
            .edgesIgnoringSafeArea(.all)
    
    //        .frame(width: UIScreen.main.bounds.width,                    // << this !!
    //               height: UIScreen.main.bounds.height, alignment: .top)
    
    

    【讨论】: