🐘
[SwiftUI] Buttonの反応がおかしい時にやること
Mastodonのアプリを作っていてSwiftUIのボタン周りでいくつかハマったところがあったので紹介します。
画像ボタンの見えない部分にタップ判定がある
次のコードは16:9の横長の画像を正方形にクロップしたボタンを作るコードです。
Button {
} label: {
Image()
.resizable()
.scaledToFill()
}
.frame(width: 100, height: 100)
.clipped()
これによって作られたボタンは、clippedされている本来画像が表示される領域にタップ判定があります。
これを防ぐためには、label側でframeを指定する必要があります。
Button {
} label: {
Image()
.resizable()
.scaledToFill()
.frame(width: 100, height: 100)
.clipped()
}
画像ボタンの見えない部分に置かれたUIViewRepresentableのタップ判定が無くなる
前項のようなボタンの周辺に、UIViewRepresentableで作ったビューを配置するとタップが効かなくなります。
下のgifでは、Buttonの上にUIViewRepresentableでラップしたUITextViewにリンクを表示していますが、ボタンの外周は反応せず左端だけが有効な状態になっています。
この問題を回避するには、UIViewRepresentableのzIndexをButtonよりも手前にすることで回避できます。
VStack {
UIKitView()
.zIndex(1) // added
Button {
} label: {
Image()
.resizable()
.scaledToFill()
.frame(width: 300, height: 200)
.clipped()
}
}
UIHostingConfigurationに乗せたButtonがスクロール中に押されてしまう
UIHostingConfigurationに乗せたボタンはViewController側にPanジェスチャが設定されているとキャンセル判定が甘くなります。
シートモーダルなどの中でUIHostingConfigurationを使うとスワイプダウンのジェスチャーと干渉します。
Discussion