UIScrollViewのは、サブビューのタッチ対触れます
-
22-08-2019 - |
質問
誰かがnoobのを整理することができますしてください?私は様々なフォーラムでこの問題を投稿し、他の回答のための多くの検索がStackOverflowのアップになっているが、何の答えを受けていないので、私は、これは場所です願っていました。
私はBeachView.h(UIScrollViewのサブクラスの、砂浜の絵が)Stone.hの乱数(UIImageViewのサブクラス、タッチを受け入れるために、ランダムな石のPNG、userInteractionEnabled = YES)で覆われてんですます。
ユーザーが触れると移動ビーチであれば、スクロールする必要があります。 ユーザーが石をタップすると、それは「touchedStone」メソッドを呼び出す必要があります。 ユーザーは何の石がないビーチをタップすると、それは「touchedBeach」メソッドを呼び出す必要があります。
さて、私は、これは死んでシンプルに聞こえる実現します。誰もが、すべてはそれにに制御を渡す必要があるタッチを受け入れるUIScrollViewの上の何かがあるかどうと言われます。私は触れてドラッグしたときにそう、それはスクロールする必要があります。私はタップし、それは石の上にある場合は、それはそう、浜タップを無視して、石のタップを受け入れるべき?
しかし、両方のビューがタップを受け入れ、touchedStoneとtouchedBeachの両方を呼び出しているようです。さらに、浜タップが最初に発生したので、私も「touchedStoneが、その後touchedBeachを実行しない場合は、」タイプフラグに入れないことができます。
ここではいくつかのコードです。 BeachView.mオン
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
if (self.decelerating) { didScroll = YES; }
else { didScroll = NO; }
UITouch *touch = [[event allTouches] anyObject];
CGPoint touchLocation = [touch locationInView:touch.view];
NSLog(@"touched beach = %@", [touch view]);
lastTouch = touchLocation;
[super touchesBegan:touches withEvent:event];
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
didScroll = YES;
[super touchesMoved:touches withEvent:event];
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
if (didScroll == NO && isPaused == NO) {
[self touchedBeach:YES location:lastTouch];
}
[super touchesEnded:touches withEvent:event];
}
Stone.mオン
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[parent stoneWasTouched]; // parent = ivar pointing from stone to beachview
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
CGPoint touchLocation = [touch locationInView:touch.view];
NSLog(@"touched stone = %@", [touch view]);
[parent touchedStone:YES location:touchLocation];
}
石タップした後、私のNSLogは次のようになります:
Touched beach = <BeachView: 0x1276a0>
ran touchedBeach
Touched Stone = <Stone: 0x1480c0>
ran touchedStone
だから、実際に両方を実行しています。私はStone.mのうち、touchesBeganとtouchesEndedを取るが、userInteractionEnabledを残せば何でも他人のは= YES、ビーチビューは、両方の登録自体に触れるが、それは(第2回)に触れビューとして石を返します。
Touched beach = <BeachView: 0x1276a0>
ran touchedBeach
Touched beach = <Stone: 0x1480c0>
ran touchedBeach
だから、私は日のためにこれをソートするためにしようとしてきたしてください。どのように私はそれがとてもタップ石のみtouchedStoneとタップビーチコールのみtouchedBeach呼び出しを行うのですか?どこが間違っているんだ?
解決
前のiPhone OS 3.0に、UIScrollViewののhitTest:withEvent:それは直接たUIEventを受け取るようにする方法は、常に場合のみ、適切なサブビューに転送し、それが判断した場合、それは、スクロールやズームに関連していない、自己を返します。
私は本当にiPhone OS 3.0それはNDA下にあるようにコメントが、チェックできなかったあなたの "iPhone SDKリリースは、iPhone OS 3.0ベータ5のためのノート":)
あなたは事前に3.0をターゲットにする必要がある場合は、、あなたはhitTestをオーバーライドすることができます:withEvent:ビーチビューでとするCGPointは石に実際にある場合は、次のビーチのタッチを無視するようにフラグを設定する
。しかし、あなたは単にあなたの呼び出し[スーパー*触れる:withEvent:]を移動しようとしているスタートにあなたのオーバーライドされたメソッドの終わりから?これは、石のタップが最初に発生する可能性があります。
他のヒント
もう-touchesBegan:
するタッチと-touchesEnded:
** UIScrollview
**サブクラスのメソッドを渡さない、アップiPhone SDK 3.0と本当です。あなたは同じではありませんtouchesShouldBegin
とtouchesShouldCancelInContentView
メソッドを使用することができます。
あなたは本当にこれが触れる取得したい場合は、これを可能にする1つのハックを持っています。
UIScrollView
のサブクラスでは、このようなhitTest
メソッドをオーバーライド
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
UIView *result = nil;
for (UIView *child in self.subviews)
if ([child pointInside:point withEvent:event])
if ((result = [child hitTest:point withEvent:event]) != nil)
break;
return result;
}
この本は触れるサブクラスあなたに渡します、しかし、あなたはスーパークラスをUIScrollView
するタッチをキャンセルすることはできません。
私はsimpleView
と同様の問題を持っていたし、それはscrollView
に追加され、私はsimpleView
に触れたときに、scrollView
は、タッチを取得するために使用し、代わりにsimpleViewの、scrollView
が移動しました。ユーザーがscrollView
に触れたし、そうでない場合はスクロールが有効になっているときにこれを避けるために、私はsimpleView
のsrcollingを無効にします。
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
UIView *result = [super hitTest:point withEvent:event] ;
if (result == simpleView)
{
scrollView.scrollEnabled = NO ;
}
else
{
scrollView.scrollEnabled = YES ;
}
return result ;
}
このはiOS7のバグに関連している可能性が
(バグレポートを提出)私の問題を確認してくださいUIScrollViewのサブクラスがiOS7 の中での挙動を変更しました。