設置したUIButtonを親Viewの外に配置してしまうとタップが反応しない。
よくあるのは✗ボタンが右上に半分はみ出しているようなカスタムViewを作ったりするとき。
この状態だとタップが反応するのは親Viewにかぶっている部分のみになる。
これはボタンの反応領域を広げてあげると解決できる。
ボタンの反応領域を広げる
カスタムView内で下記を定義してあげればOK。
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { let tapPoint = closeButton.convert(point, from: self) // ① if closeButton.bounds.contains(tapPoint) { // ② return closeButton } return super.hitTest(point, with: event) }
タップした位置を取得して、タップ位置がボタン内かどうかを判定してあげるだけ。
① タップした位置がボタンとどれくらい離れているかを取得する
let tapPoint = closeButton.convert(point, from: self) // ①
これでタップした位置が、ボタンからどれくらい離れているかが取得できる。
self
はカスタムViewのことで、つまりボタンを設置している親View。
②タップした位置がボタンの範囲内にいるかを判定する
if closeButton.bounds.contains(tapPoint) { // ② return closeButton }
タップ位置がボタンの領域内であれば、ボタンを返す。こうすることで、たとえ親Viewの領域外でも「ボタンをタップした」と認識させることができる。
つまりここでタップ領域を広げているイメージ。
全体のソース
import UIKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() let customView = CustomView(frame:CGRect(x: 100, y: 100, width: 100, height: 100)) view.addSubview(customView) } } class CustomView: UIView { var closeButton: UIButton! override init(frame: CGRect) { super.init(frame: frame) backgroundColor = .systemBlue closeButton = UIButton(frame: CGRect(x: 0, y: 0, width: 30, height: 30)) closeButton.center = CGPoint(x: bounds.maxX, y: bounds.minY) closeButton.setBackgroundImage(UIImage(systemName: "xmark.circle.fill"), for: .normal) closeButton.tintColor = .systemPink closeButton.addTarget(self, action: #selector(closeAction(_:)), for: .touchUpInside) addSubview(closeButton) } override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { let tapPoint = closeButton.convert(point, from: self) if closeButton.bounds.contains(tapPoint) { return closeButton } return super.hitTest(point, with: event) } @objc func closeAction(_: UIButton) { print("CloseButton tapped!") } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } }
参考
- Xcode11.4
- Swift5.2
- Increasing the tap area of a UIButton (Example)
- Khanlou | Hacking Hit Tests