Reputation: 1
I've got a weird behaviour of ignoresSafeArea viewModifier. As far as I understood my ContentView height is increased in height by the amount of top safe area inset. Why is it happening? And how can I avoid without using GeometryReader? Probably I don't get the idea of this view modifier so any feedback is much appreciated.
struct ContentView: View {
var body: some View {
Rectangle()
.foregroundColor(.red)
.frame(width: 400.0, height: 500)
.ignoresSafeArea(.container, edges: .top)
.background { Color.blue }
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
VStack(spacing: 0.0) {
ContentView()
Spacer()
}
}
}
Resulting layout:
I expect there is no blue background that's the result of expanded height of body
Upvotes: 0
Views: 357
Reputation: 9725
Welcome to Stack Overflow! You haven't misunderstood .ignoresSafeArea()
, so much as you are misunderstanding how the order of modifiers affects the view. With the exception of a few modifiers, all modifiers return a view wrapping the prior view. I took your code and refactored it into a single view as I think that is confusing you as well. I have commented the code to help make it clear. Each number is a view wrapped by the subsequent view:
struct IgnoresSafeAreaView: View {
var body: some View {
// 4. VStack
VStack {
// 1. Rectangle
Rectangle()
.foregroundColor(.red)
// 2. Frame
.frame(width: 400.0, height: 500)
.ignoresSafeArea(.container, edges: .top)
// 3. background
.background { Color.blue }
Spacer()
}
}
}
The code above renders exactly what was shown in your picture, because in the end, your code returned a VStack
as the view. So, you have the red rectangle view, a peek of the blue background view, and the Spacer
which shows nothing so it appears white, all sitting in the VStack
.
Where your real confusion lies is in the order of your modifiers. You first create a red rectangle. That would span the entire screen, except for the top and bottom safe areas.
You then put that rectangle inside of a frame that is a constant 400x500. It can never be more, it can never be less. That would simply center the rectangle vertically in screen, no at a size of 400x500. Adding the VStack
doesn't change that because the vertical alignment of a VStack
is centered. At this point, the VStack is the same size as the rectangle, because it has no size of its own. If you place a .background(.green)
on it, you will not see it.
This is the code as currently described:
VStack {
Rectangle()
.foregroundColor(.red)
.frame(width: 400.0, height: 500)
}
.background(.green)
Add the Spacer()
after the rectangle, and you will see the green background, and that will be into the safe areas, but the rectangle won't:
VStack {
Rectangle()
.foregroundColor(.red)
.frame(width: 400.0, height: 500)
Spacer()
}
.background(.green)
if you then add .ignoresSafeArea(.container, edges: .top)
on the rectangle, or simply .ignoresSafeArea(edges: .top)
(there is no difference to this view) you will see the 400x500 rectangle move up into the safe area. Because it is in the frame, the rectangle cannot grow, so it moves. However, the blue background still sees the rectangle without being moved up, so it lives behind where the rectangle would have been but for the .ignoresSafeArea()
. This code nicely demonstrates this:
VStack {
Rectangle()
.foregroundColor(.red.opacity(0.5))
.frame(width: 400.0, height: 500)
.ignoresSafeArea(edges: .top)
.background { Color.blue }
Spacer()
}
where the red and blue overlap, you will see purple, otherwise the opacity on the red makes it appear pink.
Now let's see order of modifiers. Reversing the .frame()
and .ignoresSafeArea()
causes the rectangle to increase in size to occupy the safe area as well, and the frame now stays put and doesn't move, so you can no longer see blue at the bottom (what I think you were originally exception)
VStack {
Rectangle()
.foregroundColor(.red.opacity(0.5))
.ignoresSafeArea(edges: .top)
.frame(width: 400.0, height: 500)
.background { Color.blue }
Spacer()
}
The final answer to this is changing the order of modifiers will completely change your results, often in unexpected ways.
Upvotes: 1