SwiftUI:防止 Image() 在屏幕边界之外扩展视图矩形

eiv*_*dml 16 swift swiftui

我正在努力实现的目标

我正在尝试创建一个 SwiftUI 视图,其中图像应扩展整个屏幕 ( edgesIgnoringSafeArea(.all)),然后在其上叠加一个视图,该视图也填充整个屏幕,但尊重安全区域。

我试过的

这是我的代码,它很接近:

struct Overlay: View {
  var body: some View {
    VStack {
      HStack {
        EmptyView()
        Spacer()
        Text("My top/right aligned view.")
          .padding()
          .background(Color.red)
      }
      Spacer()
      HStack {
        Text("My bottom view")
          .padding()
          .background(Color.pink)
      }
    }
  }
}

struct Overlay_Previews: PreviewProvider {
  static var previews: some View {
    ZStack {
      Image(uiImage: UIImage(named: "background")!)
        .resizable()
        .edgesIgnoringSafeArea(.all)
        .aspectRatio(contentMode: .fill)
      Overlay()
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

问题和经过测试的解决方案

问题是图像没有像看起来那样被剪裁,因此它将父视图扩展到大于屏幕宽度的宽度,然后使右上方对齐的红色文本框浮出屏幕(见图)。

在此处输入图片说明

我尝试.clipped()在不同的地方使用,但没有运气。GeometryReader如果可能的话,我最好避免使用。

问:如何让图像视图只填满屏幕?

ahe*_*eze 19

无需搞乱 GeometryReader!

相反,您可以使用修改器防止图像溢出.background

注意:顶部 ( OverlayView) 的视图必须填满屏幕才能.ignoresSafeArea正常工作。在这里,垫片使其填满屏幕,但.frame(maxWidth: .infinity, maxHeight: .infinity)无论如何使用它都是一个很好的做法。

struct ContentView: View {
    var body: some View {
        OverlayView()
            .frame(maxWidth: .infinity, maxHeight: .infinity)
            .background { /// here!
                Image("City")
                    .resizable()
                    .aspectRatio(contentMode: .fill)
                    .ignoresSafeArea()
            }
    }
}

struct OverlayView: View {
    var body: some View {
        VStack {
            HStack {
                Spacer()
                Text("My top/right aligned view.")
                    .padding()
                    .background(Color.red)
            }
            Spacer()
            HStack {
                Text("My bottom view")
                    .padding()
                    .background(Color.pink)
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

结果:

图片在背景中,顶部内容不会溢出

  • 这绝对是比 @Fabian 的答案更好的通用和更惯用的约束视图大小的解决方案。对于其他读者:“background()”和“overlay()”都会将您提供的视图限制在接收视图的边界内。 (3认同)

Fab*_*ian 18

在被ZStack拾取之前,您必须限制越界图像的帧大小,以避免ZStack增长,从而使Overlay失去位置。

基于父视图大小

struct IgnoringEdgeInsetsView2: View {
    var body: some View {
        ZStack {
            GeometryReader { geometry in
                Image("smile")
                    .resizable()
                    .aspectRatio(contentMode: .fill)
                    .edgesIgnoringSafeArea(.all)
                    .frame(maxWidth: geometry.size.width,
                           maxHeight: geometry.size.height)
            }
            Overlay()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

基于屏幕尺寸

struct IgnoringEdgeInsetsView: View {
    var body: some View {
        ZStack {
            Image("smile-photo")
                .resizable()
                .aspectRatio(contentMode: .fill)
                .edgesIgnoringSafeArea(.all)
                .frame(maxWidth: UIScreen.main.bounds.width, 
                       maxHeight: UIScreen.main.bounds.height)
            Overlay()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

例子