SwiftUIにてボタンをタッチしても反応しない事象に遭遇しました。
SwiftUIのボタンをタッチしても反応がない
操作手順は以下の通り。
- TextFieldをタップし、キーボードを表示
- sheetで画面Aを表示
- 端末の電源ボタンを押して画面ロック
- 画面ロック解除
- 画面Aを「スワイプダウン」で閉じる
- ボタンをタッチしても反応がない。
import SwiftUI struct SubView: View { var body: some View { VStack{ Text("SubView") } } } struct ContentView: View { @State var showSheet = false @State var message = "" var body: some View { VStack{ HStack{ TextField("Message",text: $message) }.padding(20) Button { print("Push Me") } label: { Text("Push Me") } Spacer() Button { showSheet = true } label: { Text("Show") } } .sheet(isPresented: $showSheet, content: { SubView() }) .padding(0) } }
考察
色々苦闘の挙句、どうやらタッチできないわけでなく、タッチ領域がなぜか下にずれていることがわかった。
ボタンの下の方をタップすると反応する。意味がわからない。
原因の1つとして「Spacer()」を利用していることらしい。これがないと事象は発生しない。
しかし、レイアウト上、高さが変動する領域が必要。
ひたすら海外の類似事象を探したところ、下記の解決方法を見つけた。
ベストな解決方法
.sheet(isPresented: $showSheet, content: { SubView().presentationDetents([.fraction(0.999)]) })
iOS16から利用できる「ハーフモーダル」を利用すると事象が改善された。
逆にいうと、ハーフモーダルが追加されたことによる不具合ではないかと思うが。。。
代替解決方法
また、この事象は下記の方法でも解決できることがわかっている。
sheetで表示した画面を「スワイプ」でなく、dismissで終了する。
struct SubView: View { @Environment(\.dismiss) var dismiss var body: some View { VStack{ Button { dismiss() } label: { Text("Close") } } } }
sheetの代わりに、fullScreenCoverを利用する
.fullScreenCover(isPresented: $showingModal) { SecondView() }
単純にsheetをfullScreenCoverに置き換えるだけでできる。ただし、スワイプで画面を閉じることができない。