(2022/03/27 更新)
Viewをセーフエリア外に拡張する .ignoresSafeArea() モディファイアについて解説します。
iOS14から使えるようになったモディファイアで、以前からあった .edgesIgnoringSafeArea() は deprecated(非推奨)となっています。
環境
この記事の情報は次のバージョンで動作確認しています。
【Swift】5.6
【iOS】15.4
【macOS】Monterey バージョン 12.3
セーフエリア(Safe Area)とは
iOS11以降では、特定機種に存在するノッチや画面の角丸、あるいは、OSのナビゲーションやステータスバーなどと干渉しない安全な領域を示すセーフエリアの概念があります。
開発者が作成するアプリの操作部は、原則セーフエリア内に配置する必要があります。
1 2 3 4 5 6 7 8 9 10 11 12 |
struct ContentView: View { var body: some View { ZStack { Color.yellow .border(Color.red, width: 5) Text("Safe Area") .font(.largeTitle) } } } |
SwiftUIの標準の動作では、ほとんどのViewが自動でセーフエリア内に配置されますが、.backgroundと.overlayモディファイアは独自に拡張指定できます。詳しくは、【SwiftUI】Viewの背景指定(background)、【SwiftUI】Viewの重ね合わせ(overlay)を参照してください。
ソフトウェアキーボードの扱い
iOS14からソフトウェアキーボードがセーフエリア外の扱いになりました。
これによりキーボードがアプリのコントロールと重なった時に自動で再配置されるようになっています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
struct ContentView: View { var body: some View { ZStack { Color.yellow .border(Color.red, width: 5) VStack { Text("Safe Area") .font(.largeTitle) TextField("タップでキーボード表示", text: .constant("")) .textFieldStyle(RoundedBorderTextFieldStyle()) } .padding(30) } } } |
基本的な使い方
1 2 3 |
.ignoresSafeArea(edges: Edge.Set) |
【引数】
edges(省略可)
セーフエリアを拡張するエッジ(端)を、下記のいずれかで指定します。
引数無しの場合、.all(全方向に拡張) と同じになります。
複数の方向をコレクション形式で[.top, .trailing]のように指定可能です。
プロパティ | 意味 |
---|---|
.top | 上方向に拡張 |
.bottom | 下方向に拡張 |
.leading | 左方向に拡張 |
.trailing | 右方向に拡張 |
.vertical | 垂直方向(上下)に拡張 |
.horizontal | 縦方向(上下)に拡張 |
.all | 全方向(上下左右)に拡張 (デフォルト) |
使用例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
struct ContentView: View { var body: some View { ZStack { Color.yellow .border(Color.red, width: 5) VStack { Text("Safe Area") .font(.largeTitle) TextField("タップでキーボード表示", text: .constant("")) .textFieldStyle(RoundedBorderTextFieldStyle()) } .padding(30) } .ignoresSafeArea(edges: [.bottom, .trailing]) // 下端と右端を拡張 } } |
拡張領域の指定
1 2 3 |
.ignoresSafeArea(拡張領域, edges: Edge.Set) |
第一引数に下記プロパティのいずれかを指定すると、"拡張可能な範囲"を変更できます。
.container
拡張範囲をデバイスのエッジのみに限定します。
表示領域を拡張するけどソフトウェアキーボードとは重ならないようにしたい場合に指定します。
.keyboard
拡張範囲をソフトウェアキーボードのみに限定します。
ソフトウェアキーボードが出ても画面がずれなくなります。
(具体的なユースケースが思いつきません)
.all
デバイスのエッジとソフトウェアキーボードの両方を拡張範囲とします。
未指定時のデフォルト値と同じです。
使用例
拡張領域の指定は文章にすると大変わかりにくいので、次のサンプルを使って実際に動作を確認してみると良いでしょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
struct ContentView: View { /// region private let regions: [SafeAreaRegions] = [.all, .container, .keyboard] @State private var regionSelection = 0 /// edge @State private var top: Bool = false @State private var bottom: Bool = false @State private var leading: Bool = false @State private var trailing: Bool = false private var edgeSet: Edge.Set { var edgeset: Edge.Set = [] if self.top { edgeset.insert(.top) } if self.bottom { edgeset.insert(.bottom) } if self.leading { edgeset.insert(.leading) } if self.trailing { edgeset.insert(.trailing) } return edgeset } var body: some View { ZStack { Color.yellow ScrollView { VStack { Picker(selection: $regionSelection, label: Text("")) { Text(".all").tag(0) Text(".container").tag(1) Text(".keyboard").tag(2) } .pickerStyle(SegmentedPickerStyle()) Toggle("Top", isOn: $top) Toggle("Leading", isOn: $leading) Toggle("Trailing", isOn: $trailing) Toggle("Bottom", isOn: $bottom) TextField("タップでキーボード表示", text: .constant("")) .textFieldStyle(RoundedBorderTextFieldStyle()) }.padding(50) } } .border(Color.red, width: 5) .ignoresSafeArea(regions[regionSelection], edges: edgeSet) } } |