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()..)
。这完全避免了 ZStack
和 GeometryReader
的使用,并且可能是一个更干净的解决方案。
基于父视图大小
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()
)
}
}
结果:
我想要达到的目标
我正在尝试创建一个 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()..)
。这完全避免了 ZStack
和 GeometryReader
的使用,并且可能是一个更干净的解决方案。
基于父视图大小
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()
)
}
}
结果: