2011-02-07 16 views
5

UIViewControllerサブクラスがあり、UIViewのいくつかを処理するとします。これらのUIViewsは)のUIViewControllerのviewプロパティのサブビューとして追加されます。UIView、そのスーパービュー、touchesBegan:

のUIViewController:

- (void)viewDidLoad { 
    UIImageView *smallImageView... 
    [self.view addSubview:smallImageView]; 

    UIButton *button.. 
    [self.view addSubview:button]; 

    UIView *bigUIView.. // covers the entire screen (frame = (0.0, 0.0, 1024.0, 768.0)) 
    [self.view addSubview:bigUIView]; 
... 
} 

私の知る限り、bigUIViewが最前面に表示され、画面全体を覆っているため、それはtouchesBegan:withEvent:や他のビューを受け取ることになりますたとえばbuttonはタッチイベントを受信しません。

私のアプリケーションでは、アニメーション時に他のすべてのセカンダリUI要素(UIButtonsなど)の上になければならないメインユーザーインターフェイスオブジェクト(実際にはメインゲームオブジェクト)が保持されるため、 )。しかし、私は依然としてResponder ChainにUIButtonsやその他のオブジェクトを持たせたいと思っています。

私はbigUIViewクラスに次のように実装してみました:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {  
    [self.superview touchesBegan:touches withEvent:event]; 

    ... hit test the touch for this specific uiview.. 
} 

注:

  1. bigUIViewのスーパーでは、それはそれのすべてにタッチイベントを伝播するんだ、のUIViewControllerのviewプロパティを参照サブビュー?
  2. bigUIViewは、ユーザー入力も処理するため、userInteractionEnabled = YESにする必要があります。
  3. button/smallImageViewは、メインゲームオブジェクト(サブレイヤ:bigUIView)の上に表示されるため、前面に表示できません。

ありがとうございます。

答えて

11

bigUIViewクラスのpointInside:withEvent:をオーバーライドして、その点がバックグラウンドビューの他のサブビューのフレーム矩形の内側にある場合はNOを返します。これらの他のビューの兄弟であるため、ヒットテストメカニズムは他のサブビューのテストを続け、ユーザーが触れたポイントに対応するサブビューを見つけます。

Alosでは、bigUIViewクラスではなく、UIViewControllerサブクラスでイベントフェーズメソッド(-touchesBegan:withEvent:など)を実装することを検討してください。 iOSはレスポンダチェーンのビューの背後にビューコントローラを挿入するので、他のサブビュー(たとえばボタン)の1つが傍受しない限り、イベントメッセージはビューコントローラにバブルアップします。ビューコントローラは、任意のメッセージを任意のビューに送信できます。

+0

ありがとうございます.jlehrさん、 'pointInside:withEvent:'は解決策です。ポイントが他のサブビューのフレーム矩形の内側にあるときにNOを返すことによって、 'bigUIView'の' -touchesBegan:withEvent: 'メソッドは呼び出されず、' button'のアクションがトリガされます。これは 'bigUIView'と' button'の間の結合を引き起こすことに注意してください。 'bigUIView'が画面全体をカバーしているとき、どうすれば' UIViewController'のイベントフェーズメソッドだけをインターセプトできますか? 'bigUIView'クラス内に別のメソッドシグネチャを作成し、それを" catch all "' UIViewController'クラスによって委譲させますか? –

+1

いいえ、 'bigUIView'にイベントフェーズメソッドを実装しないでください。そうすれば、メッセージは、オーバーライドされた実装(例えば、 'UIButton'またはカスタム' UIViewController'サブクラス)を持つオブジェクトに到達するまで、レスポンダチェーンの上に転送されます。 – jlehr

+1

カップリングに関しては、ビューコントローラにデリゲートメソッドを実装して、実際の決定を行うために 'bigUIView'インスタンスが呼び出せるようにすることを検討してください。このようにして、ビューコントローラは、どのビューがメッセージを取得するかを計算する役割を担い、カップリングが全くないことになります。 – jlehr

0

通常、レスポンダチェーンでは、イベントはスーパービューへのパスであり、サブビューへのパスではありません。とにかく、イベントのポイントをボタンのローカル座標系に変換し、ヒットしたら、コントローラにアクションを送信します。

+0

私は解説に感謝します。興味深い解決策です。しかし、私は 'bigUIView'(「ゲームパッケージ」(CALayers)に属する)と(IBで作成された)他のUI要素との間の高い結合を避けようとしています。ありがとう –

+1

問題ありません。 bigUIViewは、他のUI要素でも動作する必要はありません。しかし、私はjlehrの解決策が行く方法だと思う! – MHC

関連する問題