はじめに
表題の通りです。
できる限り onTapGesture { ... }
より Button
を使いましょう。
// 🔺: `onTapGesture` を `Button` として使っている
FooView(foo: foo)
.onTapGesture {
print("FooView tapped.")
}
.accessibilityAddTraits(.isButton)
// ✅: `Button` を使っている
Button {
print("FooView tapped.")
} label: {
FooView(foo: foo)
}
Button
の label
には View
を渡せるので、リファクタリングも簡単です。
環境
- OS:macOS Ventura 13.3.1
- Xcode:14.3 (14E222b)
- Swift:5.8
理由
できる限り onTapGesture { ... }
より Button
を使う理由を紹介します。
公式ドキュメントに記載されている
onTapGestureの公式ドキュメント に以下の記載があります。
Note
If you create a control that’s functionally equivalent to a Button, use ButtonStyle to create a customized button instead.
(ボタンと同等の機能を持つコントロールを作成する場合は、 ButtonStyleを使用して、代わりにカスタマイズされたボタンを作成します。)
Button
と同等のコントロールなら Button
を使いましょう、と明記されています。
最初の例では label
に FooView
をそのまま渡しましたが、 部品化するなら ButtonStyle
を実装するのがいいと思います。
PrimitiveButtonStyle
を使うのがいいとのことです。
タップ時にハイライトが付く
個人的には Button
を使う一番の理由です。
onTapGesture
だとタップ時にハイライトが付かないので、タップしたかどうかがわかりづらいです。
Button
はデフォルトでハイライトが付きます。
ただ ButtonStyle
を自作する場合、ハイライト処理を自前で実装する必要があります。
struct FloatingActionButtonStyle: ButtonStyle {
let backgroundColor: Color
let foregroundColor: Color
func makeBody(configuration: Configuration) -> some View {
configuration.label
.frame(width: 56, height: 56)
.foregroundColor(foregroundColor)
.background(backgroundColor)
.cornerRadius(16)
+ .opacity(configuration.isPressed ? 0.5 : 1)
}
}
といっても1行のみの実装で済みます。
Swift Playgroundsでスニペットを使って ButtonStyle
を作ると、最初から書かれている処理です。
おわりに
タップ時の処理に onTapGesture
を使っていたら、ぜひ Button
に置き換えてハイライトが付くライフを送りましょう