NEW: Learn to build amazing SwiftUI apps for macOS with my new book! >>

Adding bottom spacing on non-Face ID phones

Forums > SwiftUI

This question is a little bit hard to Google / phrase but easy-ish to explain visually :-)

I'm just targeting iOS 15 and using SwiftUI and would like to put a button at the bottom of the screen:

face-id-bottom

This works fine and I'm basically doing this:

List {
  Text("abc")
  ...
}
.safeAreaInset(edge: .bottom) {
  Button() label: {
    Text("Create prompt")
  }
}

That said on non-Face ID phones without the swipe indicator (excuse the terminology / I don't know how best to describe this distinction which makes it difficult to Google) the button touches the bottom of the screen which I don't want:

touch-id-bottom

While I can add e.g. .padding(.vertical) to the button and have it looks good on non-Face ID phones, it then adds unwanted spacing to Face ID phones. Is there a way to just add the spacing to non-Face ID phones?

Thanks!

1      

Yes, you can. Basically, you need to get the device type and then set the padding f.e. with a ternary operator.

Here are examples of how you get the device type. https://stackoverflow.com/questions/26028918/how-to-determine-the-current-iphone-device-model

1      

Thanks for the reply. I was hoping to find a solution that didn't involve maintaining a mapping of current and future (e.g. iPhone SE 2 was released after iPhone X but has a touch ID sensor) devices just to update the spacing. I'm curious if anyone has run into this specific problem before and if they just regularly update a list of which phones have touch ID vs. not.

I've played around around with this solution which is a little clunky but seems to work:

let button = Button {} label: {
    Text("Button")
}

if UIApplication.shared.windows.first?.safeAreaInsets.bottom == 0 {
    button.padding(.bottom)
} else {
    button
}

Basically if there's no space at the bottom of the window, add bottom padding. I factored it out into a separate modifier:

struct SafeAreaBottomPadding: ViewModifier {
    func body(content: Content) -> some View {
        if UIApplication.shared.windows.first?.safeAreaInsets.bottom == 0 {
            content.padding(.bottom)
        } else {
            content
        }
    }
}

extension View {
    func safeAreaBottomPadding() -> some View {
        modifier(SafeAreaBottomPadding())
    }
}

Which I can use like this:

button.safeAreaBottomPadding()

Generally SwiftUI is pretty good about default spacing in a variety of contexts so I was hoping there was a more idiomatic solution / I'm not sure if there any caveats to this approach, but in my limited testing it seems work.

1      

Hacking with Swift is sponsored by RevenueCat

SPONSORED Spend less time managing in-app purchase infrastructure so you can focus on building your app. RevenueCat gives everything you need to easily implement, manage, and analyze in-app purchases and subscriptions without managing servers or writing backend code.

Get Started

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.