SwiftUI Zstack – Make element ignore safe area and another one don't

9.7k views Asked by At

I have a Zstack like this:

ZStack {
  Image("beach")
    .resizable()
    .edgesIgnoringSafeArea(.all)
    .scaledToFill()

  VStack {
    // with a lot of stuff
  }
}

I want the image to ignore the safe area, but the Vstack must respect the safe area.

The image is a background image that should cover all the area.

This code I have is making the VStack full screen too and I don't want that.

Why everything is not respecting the safe area is a mystery, because the respective modifier is applied to the image only.

3

There are 3 answers

1
vacawama On BEST ANSWER

Put your image in the .background:

struct ContentView: View {
    var body: some View {
        
        VStack {
            // lots of stuff
            Color.red
            Color.blue
        }
        .background(
            Image("beach")
                .resizable()
                .edgesIgnoringSafeArea(.all)
                .scaledToFill()
        )
    }
}
0
khserver On

The reason why it doesn't work with your example is that you are using scaledToFill() modifier on image, and here it matters in this particular case.

First you declared ZStack which is itself doesn't ignore safe area. After you put Image and resizable. What resizable does, is it stretches the image to fit its view, in your case it is the ZStack.

Let's see what we have until now.We have an image which stretches till the safe area.

ZStack {
  Image("Breakfast").resizable()       

}

So from now on you put edgesIgnoringSafeArea on Image, which lets the image cover all the area(ignore safe area). Now you have Zstack which respects safe area, and Image which ignores safe area. This let you put VStack in ZStack and add staff inside it. VStack will fill its parent view, which is ZStack, so it too will respect safe area(See code and image below).

ZStack {
  Image("Breakfast").resizable().edgesIgnoringSafeArea(.all)       

  VStack {
    Text("hello")
    Spacer()
  }
}

And here at last you add .scaledToFill() modifier, which stretches the image to contain all the area, and by doing this it makes ZStack view to become the hole area, as fitting view's (ZStack, HStack, VStack) calculates its size based on its content.

Useful link:

Fitting and filling views in SwiftUI

How to resize a SwiftUI Image and keep its aspect ratio

1
TenaciousJay On

Another way that worked for me is:

struct ContentView: View {
    var body: some View {
        ZStack {
            Color.clear
                .background(
                    Image("beach")
                        .resizable()
                        .ignoresSafeArea()
                        .scaledToFill()
                )
            
            VStack {
                // lots of stuff
            }
        }
    }
}

Note: In my case, when trying the other solution of putting .background on VStack the image did not fill the entire screen, instead it shrank to fit the size of what was in the VStack.