【Swift/UIKit】タップした座標(位置)を取得する方法!touchesBegan
この記事からわかること
- Swift/UIKitでタップした座標を取得する方法
- ビューの位置
- x軸/y軸
- touchesBeganメソッドの使用方法
- location(in:)メソッドの使用方法
- 長押しやピンチなど他のジェスチャーの場合
index
[open]
\ アプリをリリースしました /
友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-
posted withアプリーチ
環境
- Xcode:15.0.1
- iOS:17.0
- Swift:5.9
- macOS:Sonoma 14.1
iOSの座標:X軸/Y軸
iOSデバイスは以下画像のように左上を(x:0,y:0)
としたX軸/Y軸として管理されており座標でビューの位置を指定することが可能になっています。
Swiftでは二次元的な視覚的描画を提供する部分はCore Graphics(コアグラフィックス)で管理されているので以下の記事も参考にしてください。
タップした座標(位置)を取得する方法
UIKitでビューをタップした座標(位置)を取得するにはビュー全体のタップイベントを監視しているtouchesBegan
メソッドをオーバーライドします。引数touches
からタッチイベントを参照することができるのでfirst
で一番前を取り出し、location(in view:)
メソッドを使用してX座標とY座標の値を取得することができます。
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
// タップイベントが発生した際の処理
if let touch = touches.first {
let location = touch.location(in: self.view)
print("Tapped at x:\(location.x) y:\(location.y)")
}
}
Tapped at x:258.3333282470703 y:172.3333282470703
location(in: self.view)
で取得できる座標値は引数に指定したビューの(x:0,y:0)座標を基準としてそこから離れている座標値になります。そのため上記のようにself.view
に付与した場合は以下のような一番左上をタップすると(x:0,y:0)
、一番右下をタップするとデバイスのサイズが取得することができます。
touchesBegan(_:with:)
公式リファレンス:touchesBegan(_:with:)
func touchesBegan(
_ touches: Set <UITouch>,
with event: UIEvent?
)
UIResponder
クラスの持つtouchesBegan
メソッドはビューで1つ以上の新しいタッチが発生したことを検知するメソッドです。
location(in view:)メソッド
func location(in view: UIView?) -> CGPoint
UITouch
クラスの持つlocation(in view:)
メソッドは引数に指定したビュー座標におけるタップ位置を返すメソッドです。
別のビューをlocation(in view:)に指定した場合
例えばUILabel
を追加して表示している場合にlocation
にUILabel
を指定すると座標計算の基準がUILabel
の一番左上(x:100,y:100)
になるのでUILabel
より左上をタップするとXもYも-の値になります。
class ViewController: UIViewController {
private var label: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
label = UILabel(frame: CGRect(x: 100, y: 100, width: 200 , height: 100))
label.text = "Hello World"
label.backgroundColor = .cyan
// UILabelはデフォルトではタッチイベントを流さないのでtrueにする
label.isUserInteractionEnabled = true
self.view.addSubview(label)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first {
let location = touch.location(in: self.label)
print("Tapped at x:\(location.x) y:\(location.y)")
}
}
}
Tapped at x:-63.333343505859375 y:-36.66667175292969
要するにlocationメソッドでは基準となるビュー(左上)を指定し、その基準点からタップされた座標がどれだけ離れているかを取得できるようになるということになります。
特定のビュー内のみでタップされた座標を検知する
touchesBegan
をオーバーライドした方法ではすべてのビューでタッチイベントが発生するたびに処理が走ってしまいます。そうではなく例えばUILabel領域内をタップされた時にタップされた座標を取得したい場合はUITapGestureRecognizer
を使用してビュー自体にタップイベントを付与することで実装できます。
ジェスチャーイベントでは引数からUITapGestureRecognizer
型を受けとることができ、ここからlocation
メソッドを呼び出すことが可能です。
class ViewController: UIViewController {
private var label: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
label = UILabel(frame: CGRect(x: 100, y: 100, width: 200 , height: 100))
label.text = "Hello World"
label.backgroundColor = .cyan
label.isUserInteractionEnabled = true
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(tapped(_:)))
label.addGestureRecognizer(tapGesture)
self.view.addSubview(label)
}
@objc func tapped(_ sender : UITapGestureRecognizer) {
let location = sender.location(in: self.view)
print("Tapped at x:\(location.x) y:\(location.y)")
}
}
これでUILabel内をタップされた時だけ座標が表示されるようになりました。基準となる点はその時に応じて変更してください。この方法を使用することでタップ以外の長押しやピンチなど他のジェスチャーイベントが行われた際の座標も取得することができるようになります。
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。