194

私はでビューを持っていますUITapGestureRecognizer。したがって、ビューをタップすると、このビューの上に別のビューが表示されます。この新しいビューには3つのボタンがあります。これらのボタンの1つを押すと、ボタンアクションは表示されず、タップジェスチャアクションのみが表示されます。そのため、これらのボタンは使用できなくなりました。イベントをこれらのボタンに到達させるにはどうすればよいですか?奇妙なことに、ボタンはまだ強調表示されています。

タップを受け取った後、UITapGestureRecognizerを削除することはできません。これを使用すると、新しいビューも削除できるためです。フルスクリーンのビデオコントロールのような動作が必要なことを意味します。

4

12 に答える 12

261

コントローラまたはビュー(ジェスチャレコグナイザを作成する方)をのデリゲートとして設定できますUITapGestureRecognizer。次に、デリゲートでを実装できます-gestureRecognizer:shouldReceiveTouch:。実装では、タッチが新しいサブビューに属しているかどうかをテストできます。属している場合は、ジェスチャ認識機能に無視するように指示します。次のようなもの:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    // test if our control subview is on-screen
    if (self.controlSubview.superview != nil) {
        if ([touch.view isDescendantOfView:self.controlSubview]) {
            // we touched our control surface
            return NO; // ignore the touch
        }
    }
    return YES; // handle the touch
}
于 2010-07-27T22:29:17.563 に答える
159

ケビンバラードの答えへのケーシーのフォローアップへのフォローアップとして:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
        if ([touch.view isKindOfClass:[UIControl class]]) {
            // we touched a button, slider, or other UIControl
            return NO; // ignore the touch
        }
    return YES; // handle the touch
}

これにより、基本的に、ボタンやスライダーなど、すべてのユーザー入力タイプのコントロールが機能します。

于 2011-09-05T04:14:56.337 に答える
107

ここでこの答えを見つけました:リンク

使用することもできます

tapRecognizer.cancelsTouchesInView = NO;

これにより、タップレコグナイザーがすべてのタップをキャッチする唯一のものになるのを防ぎます

更新-Michaelは、このプロパティを説明するドキュメントへのリンクについて言及しました:cancelsTouchesInView

于 2012-01-17T07:28:02.567 に答える
72

Kevin Ballardの回答のフォローアップとして、私はこれと同じ問題を抱えており、最終的に次のコードを使用することになりました。

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    if ([touch.view isKindOfClass:[UIButton class]]){
        return NO;
    }
    return YES;
}

同じ効果がありますが、これは任意のビュー深度の任意のUIButtonで機能します(私のUIButtonは複数のビュー深度であり、UIGestureRecognizerのデリゲートにはそれへの参照がありませんでした)。

于 2011-07-13T22:21:47.740 に答える
10

iOS 6.0以降では、デフォルトの制御アクションにより、ジェスチャ認識機能の重複が防止されます。たとえば、ボタンのデフォルトのアクションはシングルタップです。ボタンの親ビューにシングルタップジェスチャレコグナイザーが接続されていて、ユーザーがボタンをタップした場合、ボタンのアクションメソッドはジェスチャレコグナイザーではなくタッチイベントを受け取ります。これは、コントロールのデフォルトのアクションと重複するジェスチャ認識にのみ適用されます。これには、次のものが含まれます。

AppleのAPIドキュメントから

于 2013-11-20T10:16:58.117 に答える
8

これらの答えは不完全でした。このブール演算の使用方法については、複数の投稿を読む必要がありました。

*.hファイルにこれを追加します

@interface v1ViewController : UIViewController <UIGestureRecognizerDelegate>

*.mファイルにこれを追加します

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {

    NSLog(@"went here ...");

    if ([touch.view isKindOfClass:[UIControl class]])
    {
        // we touched a button, slider, or other UIControl
        return NO; // ignore the touch
    }
    return YES; // handle the touch
}
- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.



    //tap gestrure
    UITapGestureRecognizer *tapGestRecog = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(screenTappedOnce)];
    [tapGestRecog setNumberOfTapsRequired:1];
    [self.view addGestureRecognizer:tapGestRecog];


// This line is very important. if You don't add it then your boolean operation will never get called
tapGestRecog.delegate = self;

}


-(IBAction) screenTappedOnce
{
    NSLog(@"screenTappedOnce ...");

}
于 2013-08-18T23:51:17.967 に答える
7

ここからそれを行う別の方法を見つけました。各ボタンの内側にあるかどうかに関係なく、タッチを検出します。

(1)pointInside:withEvent: (2) locationInView:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer 
       shouldReceiveTouch:(UITouch *)touch {
    // Don't recognize taps in the buttons
    return (![self.button1 pointInside:[touch locationInView:self.button1] withEvent:nil] &&
            ![self.button2 pointInside:[touch locationInView:self.button2] withEvent:nil] &&
            ![self.button3 pointInside:[touch locationInView:self.button3] withEvent:nil]);
}
于 2011-08-08T12:53:28.317 に答える
7

スウィフト5

タプジェスチャ付きスーパービューのボタン

 func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
    if let _ = touch.view as? UIButton { return false }
    return true
}

私の場合、 hitTestの実装は私のために働きました。ボタン付きのコレクションビューがありました

このメソッドは、point(inside:with:)各サブビューのメソッドを呼び出して、どのサブビューがタッチイベントを受信するかを決定することにより、ビュー階層をトラバースします。trueが返された場合point(inside:with:)、指定されたポイントを含む最前面のビューが見つかるまで、サブビューの階層が同様にトラバースされます。

override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
    guard isUserInteractionEnabled else { return nil }

    guard !isHidden else { return nil }

    guard alpha >= 0.01 else { return nil }

    guard self.point(inside: point, with: event) else { return nil }

    for eachImageCell in collectionView.visibleCells {
        for eachImageButton in eachImageCell.subviews {
            if let crossButton = eachImageButton as? UIButton {
                if crossButton.point(inside: convert(point, to: crossButton), with: event) {
                    return crossButton
                }
            }
        }
    }
    return super.hitTest(point, with: event)
}
于 2019-12-05T23:07:06.783 に答える
3

これが私のために働いたリリーバラードの答えのスウィフトバージョンです:

func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
    if (scrollView.superview != nil) {
        if ((touch.view?.isDescendantOfView(scrollView)) != nil) { return false }
    }
    return true
}
于 2016-06-02T15:18:41.180 に答える
1

次のブール値を設定することにより、UITapGestureRecognizerが他のイベント(ボタンのタップなど)をキャンセルしないようにすることができます。

    [tapRecognizer setCancelsTouchesInView:NO];
于 2013-05-17T11:34:52.230 に答える
1

シナリオが次のような場合:

単純なビューがあり、そのビューにサブビューとして追加されたいくつかのUIButtons、UITextFieldコントロールがあります。ここで、コントロール(追加したサブビュー)以外のビューの他の場所に触れたときにキーボードを閉じたいと思います

次に、解決策は次のとおりです。

次のメソッドをXYZViewController.m(ビューがあります)に追加します

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self.view endEditing:YES];
}
于 2013-05-23T06:22:38.910 に答える
1

cdasherの答えを最適化すると、

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
       shouldReceiveTouch:(UITouch *)touch 
{
    return ![touch.view isKindOfClass:[UIControl class]];
}
于 2015-11-13T17:03:28.013 に答える