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

SwiftUI: Prevent Image() from expanding view rect outside of screen bounds

我想要达到的目标

我正在尝试创建一个 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()
    }
  }
}

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

问题是图像没有被剪裁成它看起来的样子,所以它将父视图扩展到大于屏幕宽度的宽度,然后使右上角对齐的红色文本框漂浮在屏幕外(见图) .

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

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

ZStack 拾取之前,您必须将越界 Image 的帧大小限制为避免 ZStack 增长,从而避免 Overlay 偏离位置。

edit: aheze 通过将 Image 放入 Overlay() 的背景中,用 GeometryReader 展示了一种使用 GeometryReader 的方法 .background(Image()..)。这完全避免了 ZStackGeometryReader 的使用,并且可能是一个更干净的解决方案。

基于父视图大小

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()
        }
    }
}

基于屏幕尺寸

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()
        }
    }
}

无需弄乱 GeometryReader。相反,您可以使用 .background() 修饰符来防止图像溢出。

struct ContentView: View {
    var body: some View {
        Overlay()
        .background( /// here!
            Image("City")
            .resizable()
            .aspectRatio(contentMode: .fill)
            .ignoresSafeArea()
        )
    }
}

结果: