🔭

【SwiftUI】safeAreaInset 観測隊

2024/11/20に公開

環境

Sequoia 15.1
Xcode 16.1
Canvas内のiPhone16 iOS18.1

上下方向の観測

2つの画像が連続しているところはスクロール操作の両端です。

ベースになるコード

, が文頭にあるのはコメントアウトON/OFFを繰り返すから。

import SwiftUI

struct ContentView: View {
    var body: some View {
        ScrollView(.vertical) {
            ForEach(1..<11) {
                Text("\($0 * $0 * $0 * $0)")
                    .font(Font.system(size: 100))
            }
        }
        .safeAreaInset(
            edge: .bottom
            ,alignment: .trailing //コメントアウトを切り替える
            ,spacing: 100 //コメントアウトを切り替える
        ) {
            Text("設定内容")
                .frame(width: 200, height: 200)
                .border(.black)
        }
    }
}

#Preview {
    ContentView()
}

edge: .top


edge: .bottom


edge: .top, alignment: .center

edge: .top, alignment: .leading

わかりにくくなってしまいましたが、スクロールビューの左端に合わせて表示しています(画面の端ではない)。

edge: .top, alignment: .trailing

わかりにくくなってしまいましたが、スクロールビューの右端に合わせて表示しています(画面の端ではない)。

edge: .top, spacing: 100


edge: .bottom, spacing: 100


左右方向の観測

縦横が入れ替わります。
2つの画像が連続しているところはスクロール操作の両端です。

ベースになるコード

, が文頭にあるのはコメントアウトON/OFFを繰り返すから。

import SwiftUI

struct ContentView: View {
    var body: some View {
        ScrollView(.horizontal) {
            ForEach(1..<6) {
                Text("\($0 * $0 * $0 * $0 * $0 * $0)")
                    .font(Font.system(size: 100))
            }
        }
        .safeAreaInset(
            edge: .leading
            ,alignment: .center //コメントアウトを切り替える
            ,spacing: 100 //コメントアウトを切り替える
        ) {
            Text("設定内容")
                .frame(width: 200, height: 200)
                .border(.black)
        }
    }
}

#Preview {
    ContentView()
}

edge: .leading


edge: .trailing


edge: .leading, alignment: .center

edge: .leading, alignment: .top

edge: .leading, alignment: .bottom

edge: .leading, spacing: 100


edge: .trailing, spacing: 100


backgroundを付ける

ベースになるコード

import SwiftUI

struct ContentView: View {
    var body: some View {

        ScrollView(.vertical) {
            ForEach(1..<11) {
                Text("\($0 * $0 * $0 * $0)")
                    .font(Font.system(size: 100))
            }
        }
        .safeAreaInset(
            edge: .top
            ,alignment: .trailing
        ) {
            Text("設定内容")
                .frame(width: 200, height: 200)
                .border(.black)
                .background(.red) //⭐️
        }
    }
}

#Preview {
    ContentView()
}

edge: .top, alignment: .leading

edge: .top, alignment: .center

edge: .top, alignment: .trailing

edge: .bottom, alignment: .leading

edge: .bottom, alignment: .center

edge: .bottom, alignment: .trailing

注意点

補完では

こんな風に出てくるので、VerticalやHorizontalが固定のように感じるが、実は定義が2つある。

@inlinable nonisolated public func safeAreaInset<V>(
edge: VerticalEdge,
alignment: HorizontalAlignment = .center,
spacing: CGFloat? = nil,
@ViewBuilder content: () -> V) -> some View where V : View

@inlinable nonisolated public func safeAreaInset<V>(
edge: HorizontalEdge,
alignment: VerticalAlignment = .center,
spacing: CGFloat? = nil,
@ViewBuilder content: () -> V) -> some View where V : View

感想

本View {

}
.safeAreaInset() {

}

本Viewに対して、「あなた safe area が削られますよ」と伝えているような感じ。

Discussion