UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

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!

2      

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

2      

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.

2      

BUILD THE ULTIMATE PORTFOLIO APP Most Swift tutorials help you solve one specific problem, but in my Ultimate Portfolio App series I show you how to get all the best practices into a single app: architecture, testing, performance, accessibility, localization, project organization, and so much more, all while building a SwiftUI app that works on iOS, macOS and watchOS.

Get it on Hacking with Swift+

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

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

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.