【Swift】UiViewのタップ領域を拡張する方法!UIEdgeInsetsの使い方

この記事からわかること

  • Swift/UIKitUIViewタップ領域拡大する方法
  • UIEdgeInsetsとは?
  • CGRectContainsPointとは?
  • point(inside point: CGPoint, with event: UIEvent?) -> Boolとは?

index

[open]

\ アプリをリリースしました /

みんなの誕生日

友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-

posted withアプリーチ

環境

この記事は以下の記事を参考にさせていただき、最新のコードに書き換えて自分の理解のために解説を増やした記事になります。

参考記事: Qiita:【iOS】UIButtonのタップ領域だけを拡大する

UIViewのタップ領域を拡張する方法

UIViewにタップなどのジェスチャーイベントを付与している場合にViewの大きさはそこまで大きくしたくないがタップ判定領域だけ拡大したい場合がありました。UXを考えた時にタップしやすい設計にするためにタップ判定領域を自由にコントロールできると便利になります。

UIViewのタップ領域を拡張するためには以下のようにタップ領域を拡張できる汎用的なビュークラスを実装します。

class ExtensionTapAreaView: UIView {

    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 CGRectContainsPoint(rect, point)
    }
}

その拡張ビュークラスをインスタンス化し拡大したい領域をUIEdgeInsetsで指定します。以下の場合は元のViewの大きさよりタップ領域のみを上下左右に20pxずつ拡大しています。

class ViewController: UIViewController {
    
    private var myView: ExtensionTapAreaView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        myView = ExtensionTapAreaView(frame: CGRect(x: 0, y: 0, width: 200 , height: 100))
        
        myView.insets = UIEdgeInsets(top: 20, left: 20, bottom: 20, right: 20)
        myView.center = self.view.center
        myView.backgroundColor = .gray
        myView.isUserInteractionEnabled = true
    
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(tapped(_:)))
        myView.addGestureRecognizer(tapGesture)
        self.view.addSubview(myView)
    }
    
    @objc  func tapped(_ sender : UITapGestureRecognizer) {
        print("タップされたよ")
    }
}
【Swift】UiViewのタップ領域を拡張する方法

実装方法の解説

ExtensionTapAreaViewクラスで実装しているのがタップ領域の拡大です。オーバーライドしているpoint(inside point: CGPoint, with event: UIEvent?) -> Bool指定されたポイントがビューの境界内にあるかどうかを判定するメソッドです。

 // 指定されたポイントがビューの境界内にあるかどうかを判定するメソッド
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool { }

引数pointにはタップされた座標が渡され、その座標が自身のViewの領域内にあればtrueをなければfalseを返します。ここでtrueを返すことができればViewに付与しているタップジェスチャーを発火させることができます。

Viewのタップ領域を拡張するためにUIEdgeInsets型で拡張させたい上下左右の余白を定義しています。UIEdgeInsets型はViewの領域を拡大/縮小する値を保持するデータクラスです。汎用性を高めるために定義時は全方向0を指定し、インスタンス化後に自身で値を変更することでタップ領域をカスタマイズすることができるようになっています。

var insets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0 )

point(inside point: CGPoint, with event: UIEvent?) -> Boolの中では指定されたUIEdgeInsetsの値をタップ判定領域に追加していきます。boundsプロパティから現在のViewの領域を取得各座標をインセットを含めた値に変更していきます。

var rect = bounds
// 元のX座標より左側に広げるためマイナスする
rect.origin.x -= insets.left
// 元のY座標より上側に広げるためマイナスする
rect.origin.y -= insets.top
// 元の横幅よりインセット分左右に広げるためプラスする
rect.size.width += insets.left + insets.right
// 元の縦幅よりインセット分上下に広げるためプラスする
rect.size.height += insets.top + insets.bottom

最後にCGRectContainsPointクラスで引数に渡した領域内に引数に渡された座標が含まれているかを判定します。

return CGRectContainsPoint(rect, point)

これでタップ領域を拡大することができているようです。

まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。

ご覧いただきありがとうございました。

searchbox

スポンサー

ProFile

ame

趣味:読書,プログラミング学習,サイト制作,ブログ

IT嫌いを克服するためにITパスを取得しようと勉強してからサイト制作が趣味に変わりました笑
今はCMSを使わずこのサイトを完全自作でサイト運営中〜

New Article

index