Self.view(UIViewCotroller
のビュー)をダブルタップすると、いくつかのコードを呼び出す機能を実装する必要があります。しかし、このビューには他のUIオブジェクトがあり、すべての認識オブジェクトをアタッチしたくないという問題があります。ビューでジェスチャーを作成する方法の下にこの方法を見つけ、それがどのように機能するかを知っています。現在、私はハンディキャップの前にいます。サブビューを無視してこの認識機能を作成するためにどの方法を選択するかです。何か案は?ありがとう。
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleDoubleTap:)];
[doubleTap setNumberOfTapsRequired:2];
[self.view addGestureRecognizer:doubleTap];
UIGestureRecognizerDelegate
オブジェクト内でself
プロトコルを採用し、ビューを確認するために以下のメソッドを呼び出す必要があります。このメソッド内で、ビューをtouch.view
に対してチェックし、適切なブール値(はい/いいえ)を返します。このようなもの:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
if ([touch.view isDescendantOfView:yourSubView]) {
return NO;
}
return YES;
}
編集:@Ianの回答もチェックしてください!
別のアプローチは、タッチのビューがジェスチャービューであるかどうかを単に比較することです。子孫は条件を通過しないためです。素敵でシンプルなワンライナー:
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
return touch.view == gestureRecognizer.view
}
また、Swiftバリアントの場合:
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
if touch.view.isDescendantOfView(yourSubView){
return false
}
return true
}
isDescendantOfView
は、受信者が特定のビューのサブビューであるか、そのビューと同一であるかを示すBoolean
値を返します。
完全なSwiftソリューション(デリゲートを実装し、認識エンジンに設定する必要があります)):
class MyViewController: UIViewController UIGestureRecognizerDelegate {
override func viewDidLoad() {
let doubleTapRecognizer = UITapGestureRecognizer(target: self, action: #selector(onBaseTapOnly))
doubleTapRecognizer.numberOfTapsRequired = 2
doubleTapRecognizer.delegate = self
self.view.addGestureRecognizer(doubleTapRecognizer)
}
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
if touch.view.isDescendantOfView(self.view){
return false
}
return true
}
func onBaseTapOnly(sender: UITapGestureRecognizer) {
if sender.state == .Ended {
//react to tap
}
}
}
Swift 5およびiOS 12の場合、UIGestureRecognizerDelegate
には gestureRecognizer(_:shouldReceive:)
と呼ばれるメソッドがあります。gestureRecognizer(_:shouldReceive:)
には次の宣言:
ジェスチャ認識エンジンがタッチを表すオブジェクトを受け取る必要があるかどうかをデリゲートに尋ねます。
_optional func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool
_
以下の完全なコードは、gestureRecognizer(_:shouldReceive:)
の可能な実装を示しています。このコードでは、ViewController
のビューのサブビュー(imageView
を含む)をタップしても、printHello(_:)
メソッドはトリガーされません。
_import UIKit
class ViewController: UIViewController, UIGestureRecognizerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(printHello))
tapGestureRecognizer.delegate = self
view.addGestureRecognizer(tapGestureRecognizer)
let imageView = UIImageView(image: UIImage(named: "icon")!)
imageView.frame = CGRect(x: 50, y: 50, width: 100, height: 100)
view.addSubview(imageView)
// ⚠️ Enable user interaction for imageView so that it can participate to touch events.
// Otherwise, taps on imageView will be forwarded to its superview and managed by it.
imageView.isUserInteractionEnabled = true
}
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
// Prevent subviews of a specific view to send touch events to the view's gesture recognizers.
if let touchedView = touch.view, let gestureView = gestureRecognizer.view, touchedView.isDescendant(of: gestureView), touchedView !== gestureView {
return false
}
return true
}
@objc func printHello(_ sender: UITapGestureRecognizer) {
print("Hello")
}
}
_
gestureRecognizer(_:shouldReceive:)
の代替実装は次のとおりです。
_func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
return gestureRecognizer.view === touch.view
}
_
ただし、この代替コードは_touch.view
_が_gestureRecognizer.view
_のサブビューであるかどうかをチェックしないことに注意してください。
クリアSwift way
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
return touch.view == self.view
}
タッチしたCGPointを使用するバリアント(Swift 4.0)
class MyViewController: UIViewController, UIGestureRecognizerDelegate {
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
// Get the location in CGPoint
let location = touch.location(in: nil)
// Check if location is inside the view to avoid
if viewToAvoid.frame.contains(location) {
return false
}
return true
}
}
gestureRecognizer API が次のように変更されていることに注意してください。
gestureRecognizer(_:shouldReceive :)
最初のパラメーターの外部ラベルのアンダースコア(スキップ)インジケーターに特に注意してください。
上記の例の多くを使用すると、イベントを受け取りませんでした。以下は、Swift(3+))の現在のバージョンで動作する例です。
public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
var shouldReceive = false
if let clickedView = touch.view {
if clickedView == self.view {
shouldReceive = true;
}
}
return shouldReceive
}
子ビューでのジェスチャーを防止する必要がありました。唯一機能したのは、最初のビューを許可および保持し、次のすべてのビューでジェスチャーを防止することです。
var gestureView: UIView? = nil
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
if (gestureView == nil || gestureView == touch.view){
gestureView = touch.view
return true
}
return false
}
Swift 4:
touch.view
はオプションになったため、@ Antoineの回答に基づいています。
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
if let touchedView = touch.view, touchedView.isDescendant(of: deductibleBackgroundView) {
return false
}
return true
}