13

アプリケーション全体で発生するアクティビティ (つまり、タッチ) を傍受しようとしています。

つまり、残りのコントロールを含むメインの UIView 内で発生したタッチ イベントの通知を受け取ろうとしています。そのためには、UIView のメソッド -hitTest:withEvent: が良い解決策だと思いました。

ただし、[super hitTest:... withEvent:...] を呼び出す前にこのオーバーライドされたメソッドに NSLog すると、任意のタッチに対して 3 回呼び出されることがわかり、受け取るイベントに違いは見られません。呼び出されるたびに。

私のアプリケーションのメインビューでメソッドを実装する方法は次のとおりです。

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    NSLog(@"hitTest:withEvent called :");
    NSLog(@"Event: %@", event);
    NSLog(@"Point: %@", NSStringFromCGPoint(point));
    NSLog(@"Event Type: %d", event.type);
    NSLog(@"Event SubType: %d", event.subtype);
    NSLog(@"---");

    return [super hitTest:point withEvent:event];
}

そして、これがこのビューでのシングルタッチの NSLog です。

2010-11-29 14:09:26.892 Application[68818:207] hitTest:withEvent called :
2010-11-29 14:09:26.892 Application[68818:207] Event: <UITouchesEvent: 0x5716d60> timestamp: 37935.2 touches: {(
)}
2010-11-29 14:09:26.892 Application[68818:207] Point: {173, 498}
2010-11-29 14:09:26.892 Application[68818:207] Event Type: 0
2010-11-29 14:09:26.892 Application[68818:207] Event SubType: 0
2010-11-29 14:09:26.893 Application[68818:207] ---
2010-11-29 14:09:26.893 Application[68818:207] hitTest:withEvent called :
2010-11-29 14:09:26.893 Application[68818:207] Event: <UITouchesEvent: 0x5716d60> timestamp: 37935.2 touches: {(
)}
2010-11-29 14:09:26.893 Application[68818:207] Point: {173, 498}
2010-11-29 14:09:26.893 Application[68818:207] Event Type: 0
2010-11-29 14:09:26.893 Application[68818:207] Event SubType: 0
2010-11-29 14:09:26.893 Application[68818:207] ---
2010-11-29 14:09:26.893 Application[68818:207] hitTest:withEvent called :
2010-11-29 14:09:26.894 Application[68818:207] Event: <UITouchesEvent: 0x5716d60> timestamp: 37944.9 touches: {(
)}
2010-11-29 14:09:26.894 Application[68818:207] Point: {173, 498}
2010-11-29 14:09:26.894 Application[68818:207] Event Type: 0
2010-11-29 14:09:26.894 Application[68818:207] Event SubType: 0
2010-11-29 14:09:26.894 Application[68818:207] ---

1回のタッチで1回だけ実行したいアクションをトリガーするために、これら3つの通知に違いを生むにはどうすればよいですか?

前もって感謝します !

4

4 に答える 4

10

実際、hitTest には 3 つの呼び出しがあります。理由は明らかではありませんが、イベントのタイムスタンプから、最初の 2 つの呼び出しが前のジェスチャの完了に関係していると推測できます。これらのタイムスタンプは、前のタッチが発生したときと常に非常に近く、現在の時刻。

これは、処理する hitTest を決定する方法です。

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
  NSTimeInterval system = [[NSProcessInfo processInfo] systemUptime];

  if (system - event.timestamp > 0.1) {
    // not the event we were interested in
  } else {
    // use this call
  }
}
于 2010-12-27T05:28:17.697 に答える
8

それでも問題が解決しない場合。

このトピックに関するいくつかの例と議論を見つけましたが、適切な解決策は非常に簡単です。

一般に、hittest は UIView または UIScrollView 内で 3 回呼び出されます。これは、ビュー階層をトラバースした結果です。

非常にシンプルで、私にとって常に適切な解決策は次のとおりです。

実装したビューに関数 hittest を実装します

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {

私にとっては、3 つの関数呼び出しはすべて常に同じ位置にあるため、場所をローカル クラスに保存するだけです。

.h ファイル内:

@interface MyScrollView : UIScrollView {
    CGPoint touchLocation_;
}

@property (nonatomic, readonly) CGPoint touchLocation;

.m ファイル内

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
    return [super hitTest:point withEvent:event];
}

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event{
// The point check you need    
    if(point.y != self.touchLocation.y){
        touchLocation_ = point;
    // The function call you need - just called once.
    }
    return [super pointInside:point withEvent:event];
}

このソリューションは、いくつかのプロジェクトで非常にうまく機能します。

于 2012-04-04T11:17:41.440 に答える
2

受け取るイベント応答の数は、ビューの階層によって異なります。

このメソッドは、各サブビューに pointInside:withEvent: メッセージを送信してビュー階層を走査し、どのサブビューがタッチ イベントを受け取るかを決定します。pointInside:withEvent: が YES を返す場合、サブビューの階層がトラバースされます。それ以外の場合、ビュー階層のブランチは無視されます。このメソッドを自分で呼び出す必要はほとんどありませんが、サブビューからタッチ イベントを非表示にするためにオーバーライドする場合があります。

このメソッドは、非表示のビュー オブジェクト、ユーザー操作が無効になっているビュー オブジェクト、またはアルファ レベルが 0.01 未満のビュー オブジェクトを無視します。このメソッドは、ヒットを判断するときにビューのコンテンツを考慮しません。したがって、指定されたポイントがそのビューのコンテンツの透明な部分にある場合でも、ビューを返すことができます。

レシーバーの境界外にあるポイントは、実際にはレシーバーのサブビューの 1 つにある場合でも、ヒットとして報告されることはありません。これは、現在のビューの clipsToBounds プロパティが NO に設定されていて、影響を受けるサブビューがビューの境界を超えている場合に発生する可能性があります。

UIView クラス リファレンスから。

簡単に言えば、タッチしたビューに 3 つのサブビューがあり、それらのビューがスーパービューとタッチ領域の境界内に表示されている場合、3 つのヒット テスト応答を受け取ります。

于 2010-11-29T13:24:44.797 に答える