如何在SwiftUI中为完整视图添加背景图片

24

我是新手 SwiftUI,我想设计一个带有几个控件和背景图像的自定义视图。 背景图像应覆盖整个视图。 它应该看起来像屏幕上的水印。 我如何使用 SwiftUI 实现这一点?

7个回答

46

使用ZStack,但不要使用UIScreen

var body: some View {
    ZStack {
        Image("BG")
            .resizable()
            .scaledToFill()
            .edgesIgnoringSafeArea(.all)

        Text("Hello world")
    }
}

如果你的应用程序支持多屏应用、可调整大小的窗口、多窗口应用等功能,使用 UIScreen 将导致应用程序出现不良行为。


但是如何使文本(在我的情况下,我有一些滚动视图)不忽略安全区域? - LetsGoBrandon

19
尝试这个:
    var body: some View {
    ZStack {
        Text("Hello")
    }
    .background(
        Image("Background")
            .resizable()
            .edgesIgnoringSafeArea(.all)
            .frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
    )
}

7

更新

使用iOS 15 Xcode 13.2版本。

public extension View {
    func fullBackground(imageName: String) -> some View {
       return background(
                Image(imageName)
                    .resizable()
                    .scaledToFill()
                    .edgesIgnoringSafeArea(.all)
       )
    }
}

使用

YourView
.fullBackground(imageName: "imageName")

更新结束

旧回答

我更喜欢使用@ViewBuilder

用法:

BackgroundView(imageName: "image name") {         
     Text("Hello")                               
}

@ViewBuilder

public struct BackgroundView <Content : View> : View {
    public var content : Content
    public var imageName: String
    public var opacity: Double
    public init(imageName: String, opacity: Double=1,@ViewBuilder content: () -> Content) {
        self.content = content()
        self.imageName = imageName
        self.opacity = opacity
    }
    
    public var body: some View {
        GeometryReader { geo in
            ZStack {
                Image(imageName)
                    .resizable()
                    .scaledToFill()
                    .edgesIgnoringSafeArea(.all)
                    .frame(width: geo.size.width, height: geo.size.height, alignment: .center)
                    .opacity(opacity)
                content
            }
        }
    }
}

2

Mojtaba的回答不完整。问题在于图像的边界框可能超出屏幕,导致不良行为。为了纠正这个问题,我们需要添加.frame。这将确保图像与屏幕一样大,并修复我们的问题。

struct BackgroundView: View {
    var body: some View {
        GeometryReader { proxy in
            Image("Background")
                .resizable()
                .scaledToFill()
                .frame(width: proxy.size.width, height: proxy.size.height)
                .clipped()
        }.ignoresSafeArea()
    }
}

0

如果您只想使用全屏宽度和高度,并且不关心图像的纵横比,您可以使用UIScreen大小的几何读取器。

.frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)

这行代码将把图像设置为设备的最大尺寸。根据您的父视图和设备,您可能需要使用:

.edgesIgnoringSafeArea(.all)

这将忽略 iPhone X 及以上设备上的安全区域。


0
您可以使用以下方式通过ZStack来实现这一点。例如,您可以在Image上添加更多控制,比如我添加了Text()
var body: some View {
      ZStack{
           Image("your image")
        .frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
           Text("Hello World").foregroundColor(.white).font(.system(size: 20)).bold()
       }
}

您可以使用以下方法忽略 SafeArea

.edgesIgnoringSafeArea(.all)

0
struct LoginView: View {
    var body: some View {
        Image("imageName")
            .resizable()
            .ignoresSafeArea(.all)
    }
}

2
如果能解释这段代码是如何回答问题的,那就更有用了。其他回答对这个问题有很好的解释。新的回答应该提供新的见解和良好的解释。 - AdrianHHH

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接