✏️

【Swift5】カスタムボタンのタップ領域を拡大する

2022/03/03に公開

※以下の記事のコードをベースとしたSwift5版となります。
https://qiita.com/KokiEnomoto/items/264f26bfa92d06b1996e


カスタムボタンのタップ領域を拡大するには、以下のようなボタンを作れば実現できます。

import UIKit

class CustomButton: UIButton {
    var insets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
    
    override func point(inside point: CGPoint, with 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 //④

        return rect.contains(point) //⑤
    }
}

pointメソッドは、タップされた座標がそのViewの範囲内かを判定します。
オーバーライドで何をしているかというと

① ボタン自身の左上のx座標からinsets.left分左に座標をずらす
② ボタン自身の左上のy座標からinsets.top分上に座標をずらす
③ ボタン自身のwidthにinsets.leftをinsets.rigntの値を加算する
④ ボタン自身の高さにinsets.topとinsets.bottomの値を加算する
⑤ ①②のx,y座標を基点として横幅③、高さ④の領域にタップした位置が含まれているかを判定する

という処理を行なっています。

簡単に言えば、
各方向に対して拡大したい大きさをinsetsに指定してあげればその分ボタンの領域が変更される
ということです。
マイナスを指定することで領域を縮小することも可能です。

ここからサンプルコードでみていきます。
CustomButtonを使用してラベルの文言がON,OFFに切り替わるボタンを作成します。

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var customButton: CustomButton!
    private var isOn: Bool = false
    
    override func viewDidLoad() {
        super.viewDidLoad()
        customButton.insets = UIEdgeInsets(top: 100, left: 50, bottom: 0, right: -50)
        customButton.addTarget(self, action: #selector(tapButton), for: .touchUpInside)
    }

    @objc func tapButton(_ sender: UIButton) {
        isOn.toggle()
        if isOn {
            statusLabel.text = "ON"
        } else {
            statusLabel.text = "OFF"
        }
    }
}

CustomButtonの使い方としては、拡大(縮小)したい方向と大きさをinsetsに指定します。
わかりやすくするためviewに色をつけます。


黒枠:cutomButton(1辺50ptの正方形)
紫:1辺50ptの正方形
赤:1辺100ptの正方形
緑:1辺150ptの正方形

中央の黒枠で囲まれたcustomButtonに対してcustomButton.insets = UIEdgeInsets(top: 100, left: 50, bottom: 0, right: -50)を指定しているので、上方向に100pt、左方向に50ptのタップ領域を拡大、下方向は変動はなく、右は50ptのタップ領域縮小を行ってます。

タップできない領域をグレーにしたものが以下となります。
元々の領域(紫の正方形)からタップができる領域が変更されました。

Discussion