兄弟サブビューはiPhoneで接触しません

2つのサブビューを持つビュー( bottomChild )の1つ( topChild )に1つのビュー( parent )があります。

画面をタップすると、 topChild parent だけがタッチイベントを受信します。

タッチイベントを bottomChild に伝播するために変更する必要があるのは何ですか?

コード:

- (void)viewDidLoad
{
    [super viewDidLoad];
    MYView* parent = [[MYView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
    parent.tag = 3;
    parent.backgroundColor = [UIColor redColor];

    MYView* bottomChild = [[MYView alloc] initWithFrame:CGRectMake(0, 0, 90, 90)];
    bottomChild.tag = 2;
    bottomChild.backgroundColor = [UIColor blueColor];
    [parent addSubview:bottomChild];

    MYView* topChild = [[MYView alloc] initWithFrame:CGRectMake(0, 0, 80, 80)];
    topChild.tag = 1;
    topChild.backgroundColor = [UIColor greenColor];
    [parent addSubview:topChild];
    [self.view addSubview:parent];
}

MYView touchesBegan のみを記録する UIView のサブクラスです。

- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    NSLog(@"%d", self.tag);
    [super touchesBegan:touches withEvent:event];
}

結果:

enter image description here

緑色の領域に触れると、次のログが生成されます。

TouchTest[25062:f803] 1
TouchTest[25062:f803] 3

私の最初のアイデアは、すべての touchesSomething 呼び出しをその子に伝える(親) (B)どの子が親にイベントを送信したかわからず、同じビューに touch メッセージを2回送信すると、

質問をした後、 hitTest を上書きすることを提案するこの投稿が見つかりました。/code>を押して、タッチを受け取ったビューを変更します。私はこのアプローチを試み、問題があればそれを更新します。

0

2 答え

興味深い問題です。おそらく、あなたが物事を構造化したやり方を考え直すことによって、最善の方法で対処されたものです。しかし、現在のトップビューでタッチイベントをキャッチする必要があることを示唆するように動作させるには、それを親に渡してから親ビューのすべてのサブビューに伝播させます。この作業を行うには、すべてのビューで何もしないように touchesBegan:(またはタッチを傍受する他の方法)が必要です。親ビューから呼び出されるメソッドでのみアクションを実行します。

実際に別の言い方をすれば、ビューに触れずに親ビュービューに通知し、必要に応じて必要に応じてサブビューメソッドを呼び出して、望む効果を引き出すことができます。

- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

   //Do nothing, parent view calls my parentNotifiedTouchesBegan method
    [self.superview touchesBegan:touches withEvent:event];
}

- (void) parentNotifiedTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

   //Act on the touch here just as my sibling views are doing
}

super をそのコードの self.superview に変更しました。 parent のメソッドは、あなたがやっていることと、 parentNotifiedTouchesBegan にある呼び出し場所に応じて呼び出すこともできます。

どのサブビューがイベントを送信したかを知ることができます。カスタムメソッドを使用して、 touchesBegan:を呼び出す代わりにスーパービューに通知してください。 self 引数を使用します。

1
追加された
ありがとうございました!このソリューションはジェスチャ認識ツールと互換性がありますか?一見すると、私はこの道を行くならば、私は車輪を再実装する必要があるように見えます。
追加された 著者 hpique,
そして私は物事を再構築したいと思っていますが、私の場合はどうなっているのでしょうか。 topChildは透過性を持ち、topChildとbottomChildの両方が "動く"ことができます(したがって、topChildはbottomChildのサブビューにはなれません)。両方とも接触する必要があります。
追加された 著者 hpique,
それは私が今試みていたものでした!それは、私はそれが "手動で"行われなければならないことが非常に奇妙であると感じました。私はこれがかなり一般的な問題だと思います。
追加された 著者 hpique,
可能であれば、単純なタッチではなく、コールバックで受け取ったgestureRecognizerオブジェクトを親に渡すだけです。少なくとも私が便利なのは、このプロジェクトではUIPinchGestureRecognizerのために働くでしょう。
追加された 著者 Adam Eberbach,
今では、サブビューでイベントをキャッチする必要はないと考えています。実際には、基本ビューにすべてが得られるようにインタラクションを無効にすることができます。通知ステップを実行する必要はありません。ベースビューをキャッチしてすべてを解釈し、ビューを動作させます。ポイント( - (CGPoint)convertPoint:(CGPoint)ポイントtoView:(UIView *)ビュー)をサブビューのフレーム(CGRectContainsPoint)と比較することによって、イベントを取得するビューを分離できるはずです。
追加された 著者 Adam Eberbach,

あなたが子供たちに触れる必要がない場合は、

bottomChild.userInteractionEnabled = NO;
topChild.userInteractionEnabled = NO;
0
追加された