5

セットアップ:親ビューAがあります。子ビューBがあります。Bは部分的にAの境界の内側にありますが、部分的に外側にあります(AにはclipsToBounds = falseがあります)。UITapGestureRecognizer(UITGR)をBにアタッチしました。

観察:Aの境界内にあるBの部分をタップするとUITGRは正常に起動します。Aの境界外にあるBの部分をタップするとUITGRは起動しません。

期待/質問:Aの境界外にあるBの部分をタップしたときにUITGRを起動するにはどうすればよいですか?

4

3 に答える 3

7

この引用は、なぜそれがそのように振る舞うのかについてのあなたの質問に答えます:

タッチイベント。ウィンドウオブジェクトは、ヒットテストとレスポンダーチェーンを使用して、タッチイベントを受信するビューを見つけます。ヒットテストでは、ウィンドウはビュー階層の最上位のビューでhitTest:withEvent:を呼び出します。このメソッドは、YESを返すビュー階層内の各ビューでpointInside:withEvent:を再帰的に呼び出し、タッチが行われた境界内のサブビューが見つかるまで階層を下に進みます。そのビューがヒットテストビューになります。(ソース

UITapInSubviewsView回避策の1つは、次の定義を使用して独自の回避策を作成することhitTestです。

(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    NSEnumerator *reverseE = [self.subviews reverseObjectEnumerator];
    UIView *iSubView;
    while ((iSubView = [reverseE nextObject])) {

        UIView *viewWasHit = [iSubView hitTest:[self convertPoint:point toView:iSubView] withEvent:event];
        if(viewWasHit)
           return viewWasHit;
     }
     return [super hitTest:point withEvent:event];
}

次に、このクラスを親ビューに使用します。

(このコードは数週間前のSOからの投稿で見つかりましたが、もう見つからないようです。プロジェクトからコピーしただけです)。

于 2012-05-17T08:31:08.547 に答える
1

Swift 4.2に対する@sergioの回答の更新:

override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
    let reversedSubviews = subviews.reversed()
    let hitSubview = reversedSubviews
        .first(where: { $0.hitTest(convert(point, to: $0), with: event) != nil })
    if hitSubview != nil {
        return hitSubview
    }

    return super.hitTest(point, with: event)
}
于 2019-02-15T21:06:58.220 に答える
0

ビューAに対して独自のヒットテスト関数を作成する必要があります。

この質問も見てください:UITapGestureRecognizerがディープビュー階層でトリガーされない

于 2012-05-16T14:38:53.327 に答える