SwiftUI で画面下部にボタンを置く

NG

画面下部にボタンを置く場合、 bottom の Safe Area に被らないように置かないといけない。

何も考えずに置くと、下記のように Safe Area まで拡張されずに残念な感じになる。

VStack(spacing: .zero) {
    List(0..<100) { index in
        Text("\(index)")
    }

    Button("Button", action: {})
        .frame(maxWidth: .infinity, minHeight: 44.0)
        .background(Color.orange)
}

f:id:komaji504:20210604202544j:plain:w375

NG

Safe Area までコンテンツを拡張しようと思って VStack に .ignoresSafeArea(edges: .bottom) をつけると、確かに拡張はされているが Safe Area に表示されるホームインジケータと位置が被ってしまって Human Interface Guidlines 的にも NG。

f:id:komaji504:20210604202540j:plain:w375

VStack(spacing: .zero) {
    List(0..<100) { index in
        Text("\(index)")
    }

    Button("Button", action: {})
        .frame(maxWidth: .infinity, minHeight: 44.0)
        .background(Color.orange)
}
.ignoresSafeArea(edges: .bottom) // NG

OK

ボタンの背景色だけを Safe Area まで拡張するには、下記のように .background() で指定している Color に対してだけ .ignoresSafeArea(edges: .bottom) を指定してやれば良い。

VStack に対しては .ignoresSafeArea(edges: .bottom) を指定しないのがキモ。

VStack(spacing: .zero) {
    List(0..<100) { index in
        Text("\(index)")
    }

    Button("Button", action: {})
        .frame(maxWidth: .infinity, minHeight: 44.0)
        .background(Color.orange.ignoresSafeArea(edges: .bottom)) // OK
}

f:id:komaji504:20210604202535j:plain:w375