アプリ開発をしていると、実機でデバッグした時にボタンのタップ領域が狭くて押しづらいと思うことがよくあります。
ボタンのサイズを大きくすることで解決することはできますが、アプリの見た目が不格好になってしまうため、デザイナーさんからのOKは貰いないかと思います。
この記事ではボタンのサイズを大きくすることなく、ボタンのタップ領域だけを拡大する方法を紹介したいと思います。
実装
まずは UIButton を継承した ExpansionButton クラスを作ります。
class ExpansionButton: UIButton {
}
拡大するタップ領域の範囲を保持するプロパティ insets を追加します。
class ExpansionButton: UIButton {
var insets = UIEdgeInsetsMake(0, 0, 0, 0)
}
次にUIButtonのタップ領域を拡大するの処理を記載しますが、まずはタップイベントが発火するまでの流れを簡単に説明したいと思います。
画面上のどこかをタップした時、UIViewのhitTest:withEvent:
メソッドが呼び出されます。
このメソッドの中でさらにpointInside:withEvent:
メソッドが呼ばれ、true
が返された場合にそのViewのタップイベントが発火します。
つまり、pointInside:withEvent:
メソッドの中でViewのサイズを偽造してしまえば、Viewの領域外からでもタップイベントを発火させることができるのです。
上記の説明を踏まえ、 ExpansionButton クラスの実装は最終的に以下のようになります。
class ExpansionButton: UIButton {
var insets = UIEdgeInsetsMake(0, 0, 0, 0)
override func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool {
var rect = bounds
rect.origin.x -= insets.left
rect.origin.y -= insets.top
rect.size.width += insets.left + insets.right
rect.size.height += insets.top + insets.bottom
// 拡大したViewサイズがタップ領域に含まれているかどうかを返します
return CGRectContainsPoint(rect, point)
}
}
使い方は以下のようになります。
class ViewController: UIViewController {
@IBOutlet weak var button: ExpansionButton!
override func viewDidLoad() {
super.viewDidLoad()
button.insets = UIEdgeInsetsMake(50, 50, 50, 50)
}
...
}
おわりに
この記事ではUIButtonを例に記載しましたが、UIViewを継承していれば pointInside:withEvent:
メソッドが呼ばれるので、他のViewでもタップ領域を拡大することができます。