Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 869
Duck Avatar asked Oct 12 '20 16:10

Duck


People also ask

How do I avoid safe area in SwiftUI?

By default, SwiftUI place views only inside the safe area. Here is the example showing that. But we can change this behavior using the ignoresSafeArea view modifier. The ignoresSafeArea view modifier expands the view and fills the space by ignoring the safe area.


3 Answers

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()
        )
    }
}
like image 184
vacawama Avatar answered Nov 11 '22 02:11

vacawama


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

like image 23
khserver Avatar answered Nov 11 '22 00:11

khserver


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.

like image 44
TenaciousJay Avatar answered Nov 11 '22 01:11

TenaciousJay