1

私は3つ持っていますUIViews

ビュー

B1およびB2はのサブビューですA

B1B21つ以上のサブビューがある場合があります。

同時に1つのビューにしか触れられないようにしたいと思います。

例えば:

ユーザーは人差し指(またはそのサブビューの1つB1)に触れてから、人差し指を離さずにB22番目の指(またはそのサブビューの1つ)に触れます。これで、B1すべてのイベントをその範囲内で受信する必要がありますが、受信する必要はありませんB2。逆に同じこと。

これらのビューをサブクラス化せずにこれを達成することは可能ですか?

そうでない場合、それを行うための最も簡単でクリーンな方法は何ですか?

編集:

についてexclusiveTouchmultipleTouchEnabled

これらのプロパティは私の問題には無効です。

multipleTouchEnabled:マルチタッチイベントが同じビューで配信されるかどうかのみを決定します。したがって、ビューA(とにかくデフォルト)でマルチタッチを無効にしても、ビューB1とB2が同時にタッチイベントを受信するのをブロックすることはありません。

exclusiveTouch:どちらも動作しません。私が理解している限り、ビューのフレーム内exclusiveTouchでのみ機能します。したがって、ビューB1とB2を設定しても効果はありません。参考のために、次の2つのスタックオーバーフローを参照してください。exclusiveTouch

UIView ExclusiveTouchプロパティがブロックされないのはなぜですか?

UIView.exclusiveTouchが機能しないのはなぜですか?

4

3 に答える 3

1

B1 と B2 を と の両方に設定してみてくださいexclusiveTouchmultipleTouchEnabledYES

編集:「B1はその境界内のすべてのイベントを受け取る必要があります」という言葉から、サブビューではなく、B1とB2で直接タッチを受け取りたいと想定しています。タッチを B1/B2 境界に制限したいがサブビューでそれらを処理したい場合は、B1 と B2、または A をサブクラス化する必要があると思います。

編集 2 : インタラクティブな B1 と B2 のサブビューの場合、これらのプロパティをYESすべてのインタラクティブなサブビューに (再帰的に) 設定する必要があります。しかし、これにより、B1 と B2 の間だけでなく、すべてのサブビューがタッチに対して相互に排他的になります。

于 2012-11-01T01:16:51.207 に答える
0

これは、サブクラス化なしでは不可能だと思います。誰かが私が間違っていることを証明できるなら、彼らの解決策を喜んで見てみたい. とにかく、これは私がそれを解決した方法です:

まず、ビューをサブクラス化Aし、サブクラスを呼び出しますParentViewB1ParentView にはおよびへのポインタが必要B2です。また、現在選択されているビューを保存するために後で使用する追加のポインターも追加します。次に、オーバーライドしますhitTest

@interface ParentView : UIView
    @property (nonatomic, strong) UIView* viewB1;
    @property (nonatomic, strong) UIView* viewB2;
    @property (nonatomic, strong) UIView* currentlyTouchedView;
@end

@implementation ParentView

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

    if (self.currentlyTouchedView == nil) {
        if (CGRectContainsPoint(self.viewB1.frame, point)) {
            self.currentlyTouchedView = viewB1;
        }else if(CGRectContainsPoint(self.viewB2.frame, point)) {
            self.currentlyTouchedView = viewB2;
        }
    }else {
        if (!CGRectContainsPoint(self.currentlyTouchedView.frame, point)) {
            return nil;
        }
    }

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

@end

つまり、このコードが行うことは、最初に触れたビューを保存することです。すでに格納されている場合は nil on を返しhitTest、追加のタッチ イベントを使い果たします。

では、どこでcurrentlyTouchedViewnil に設定を戻すのでしょうか? そのために、サブクラス化UIWindowしてオーバーライドsendEventし、すべてのタッチが終了したかどうかを確認します。

@implementation EventOverrideWindow

- (void)sendEvent:(UIEvent *)event {
    [super sendEvent:event];
    BOOL allTouchesEnded = YES;
    for (UITouch* touch in event.allTouches) {
        if (touch.phase != UITouchPhaseCancelled && touch.phase != UITouchPhaseEnded) {
            allTouchesEnded = NO;
            break;
        }
    }

    if (allTouchesEnded) {
        ParentView* parentView = ((AppDelegate*)[UIApplication sharedApplication].delegate).parentView;

        parentView.currentlyTouchedView = nil;
    }
}

@end

これは非常にエレガントな解決策ではないことはわかっています。誰かがより良いアイデアを持っていれば幸いです。

于 2012-11-06T00:24:55.283 に答える
0

B1 または B2 がタッチされたら、そのビューに対して に設定exclusiveTouchし、タッチが終了したら再び に設定します。これは、排他ビューのみがタッチを受け取ることを意味します。YESNO

排他的なビューの境界外にタッチしたい場合は、ビューを排他的にするときにビューへの参照をどこかに保存し ( )、ビュー A (または任意のスーパービュー) をmyExclusiveViewオーバーライドして、それを返すことができます。hitTest:withEvent:[myExclusiveView hitTest:withEvent:]

于 2012-11-01T01:33:48.167 に答える