How can I use edgesIgnoringSafeArea in SwiftUI, but make a child view respect the safe area?
Solution 1
You can access the height of the safe area using a GeometryReader. Then you could use the height of the safe area as bottom padding or offset on your button.
https://developer.apple.com/documentation/swiftui/geometryproxy
struct ContentView: View {
var body: some View {
GeometryReader { proxy in
ZStack(alignment: .bottom) {
List {
Text("Item 1")
Text("Item 2")
Text("Item 3")
}
HStack {
Spacer()
Button(action: {
// do something
}){
Text("Button")
.font(.title)
.padding()
.background(Color.green)
.foregroundColor(.white)
.cornerRadius(15)
}
.padding(.bottom, proxy.safeAreaInsets.top)
Spacer()
}.background(Color.blue)
}.edgesIgnoringSafeArea(.bottom)
}
}
}
Solution 2
Whatever view you draw in the background modifier will use the frame of the view it's modifying. So you need to tell THAT view to ignore the safe area.
.background(Color.blue.edgesIgnoringSafeArea(.bottom))
Solution 3
edgesIgnoringSafeArea(_:) is Deprecated
use the following:
.background(Color.blue.ignoresSafeArea(edges: .bottom))
Solution 4
Adding on to @Joe Susnick's answer, the full code is:
VStack {
}.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color(red: 0.357, green: 0.784, blue: 0.016, opacity: 0.5).ignoresSafeArea()
)
Anything inside of VStack respects the safe area whereas the background fills the whole screen.
Related videos on Youtube
gohnjanotis
Updated on September 16, 2022Comments
-
gohnjanotis over 1 year
I'm building a UI is SwiftUI with a list view, and I want to put a panel over part of the list view with a button on it.
On devices with a safe area at the bottom (that don't have a physical home button) I want the panel to go to the bottom of the screen. But I want to make sure that the button on the panel doesn't extend into the safe area.
In my example code, the
HStack
is the panel that contains the button. I tried adding.edgesIgnoringSafeArea(.bottom)
to it, but that doesn't allow it to extend to the bottom. This is kind of confusing to me, because the List that's in the sameZStack
extends into the bottom safe area.When I add
.edgesIgnoringSafeArea(.bottom)
to theZStack
, theHStack
(blue panel) is allowed to extend into the safe area at the bottom of the screen. This is what I want, but then once I do that, how can I tell theButton
that's a child of theHStack
to not ignore the safe area?I know how I would do this in UIKit, but I'm really hoping to be able to build this UI in SwiftUI. I could manually add some padding or Spacers to add extra padding under the
Button
to account for the safe area, but then there would be extra spacing on devices with a home button that don't have a bottom safe area. I'd like to figure out an elegant solution where I can rely on the system to define its safe areas instead of manually defining any spacing numerically or creating conditional situations for different devices.struct ContentView: View { var body: some View { ZStack(alignment: .bottom) { List { Text("Item 1") Text("Item 2") Text("Item 3") } HStack { Spacer() Button(action: { // do something }){ Text("Button") .font(.title) .padding() .background(Color.green) .foregroundColor(.white) .cornerRadius(15) }.padding() Spacer() }.background(Color.blue).edgesIgnoringSafeArea(.bottom) } } }
-
smat88dd over 3 yearsYeah, very helpful :)
-
David Seek over 3 yearsBest answer. Makes me angry that this is not accepted
-
FitzChill over 3 yearsJust Saved my day
-
theMoonlitKnight about 3 yearsusing
.vertical
instead of.bottom
you can extend the background at the top too -
Olof_t about 3 yearsThis doesn't work inside a NavigationView, also a bad answer (see @Joe Susnick's answer).
-
heiko about 3 yearsThat's it! Best answer. Should be on top.
-
aheze about 3 yearsUnfortunately using GeometryReader can create all sorts of spacing problems... it expands to take up all available space.
-
Big_Chair over 2 yearsHow would you do this if the background is an Image, because in that case it doesn't work.
-
DragonCherry over 2 yearsThanks, this must be the best answer. It seems weird at first, but we have to keep this pattern while we using SwiftUI!