简体   繁体   中英

How to add background image to complete view in SwiftUI

I am new to SwiftUI. I want to design a custom view with few controls and a background image. The background image should cover the complete view. It should look like a watermark for the screen. How can I achieve this using SwiftUI?

Use ZStack but Don't use UIScreen :

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

        Text("Hello world")
    }
}

Using UIScreen will lead your app to undesired behavior if you are supporting multiscreen app, resizable windows, multiwindow app, etc.

Try this:

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

If you just want to use the full screen width and height, and you don't bother about the aspect ratio of the image, you can either use a geometry reader of the UIScreen size's.

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

This line of code will set the Image to the max size of the device. Depending on your parent view and device, you may need to use:

.edgesIgnoringSafeArea(.all)

This will ignore the safe area's on iPhone X devices and above.

You can achieve this using ZStack like below. You can add more control on Image for example I added 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()
       }
}

You can Ignore SafeArea using

.edgesIgnoringSafeArea(.all)

I prefer a @ViewBuilder

Usage:

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

The answer of Mojtaba is incomplete. The problem is the bounding box of the image can exceed the screen leading to undesired behavior. To correct this we need to add .frame to the mix. This will make sure the image is as large as the screen and fixes our problem.

var body: some View {
    ZStack {
        Image("Background")
            .resizable()
            .scaledToFill()
            .frame(minWidth: 0, maxHeight: .infinity)
            .edgesIgnoringSafeArea(.all)

        Text("Hello world")
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM