UIScrollView 触摸与子视图触摸

时间:2022-11-15
本文介绍了UIScrollView 触摸与子视图触摸的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

请有人帮忙解决一个菜鸟吗?我已经在各种论坛上发布了这个问题并且没有收到任何答案,而许多其他答案的搜索都出现了 stackOverflow,所以我希望这是这个地方.

Please can someone help sort a noob out? I've posted this problem on various forums and received no answers, while many searches for other answers have turned up stackOverflow, so I'm hoping this is the place.

我有一个 BeachView.h(UIScrollView 的子类,沙滩的图片),上面覆盖着随机数的 Stone.h(UIImageView 的子类,石头的随机 PNG,userInteractionEnabled = YES 接受触摸).

I've got a BeachView.h (subclass of UIScrollView, picture of a sandy beach) covered with a random number of Stone.h (subclass of UIImageView, a random PNG of a stone, userInteractionEnabled = YES to accept touches).

如果用户在海滩上触摸和移动,它应该滚动.如果用户点击石头,它应该调用方法touchedStone".如果用户点击没有石头的海滩,它应该调用方法touchedBeach".

If the user touches and moves on the beach, it should scroll. If the user taps a stone, it should call method "touchedStone". If the user taps the beach where there is no stone, it should call method "touchedBeach".

现在,我意识到这听起来很简单.每个人都告诉我,如果 UIScrollView 上有什么东西可以接受触摸,它应该将控制权传递给它.所以当我触摸和拖动时,它应该滚动;但是如果我点击,它在石头上,它应该忽略海滩水龙头并接受石头水龙头,是吗?

Now, I realize this sounds dead simple. Everyone and everything tells me that if there's something on a UIScrollView that accepts touches that it should pass control on to it. So when I touch and drag, it should scroll; but if I tap, and it's on a stone, it should ignore beach taps and accept stone taps, yes?

但是,似乎两个视图都接受了点击并调用了touchedStone 和touchedBeach.此外,海滩水龙头首先发生,所以我什至不能输入如果接触石头,则不要运行接触海滩"类型的标志.

However, it seems that both views are accepting the tap and calling both touchedStone AND touchedBeach. Furthermore, the beach tap occurs first, so I can't even put in a "if touchedStone then don't run touchedBeach" type flag.

这里有一些代码.在 BeachView.m

Here's some code. On 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];
}

在石头上.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 如下所示:

After a stone tap, My NSLog looks like this:


Touched beach = <BeachView: 0x1276a0>
ran touchedBeach
Touched Stone = <Stone: 0x1480c0>
ran touchedStone

所以实际上两者都在运行.更奇怪的是,如果我将 touchesBegan 和 touchesEnded 从 Stone.m 中取出,但保留 userInteractionEnabled = YES,则 beachView 会自行注册这两个触摸,但将 Stone 作为它触摸的视图返回(第二次).

So it's actually running both. What's even stranger is if I take the touchesBegan and touchesEnded out of Stone.m but leave userInteractionEnabled = YES, the beachView registers both touches itself, but returns the Stone as the view it touched (the second time).


Touched beach = <BeachView: 0x1276a0>
ran touchedBeach
Touched beach = <Stone: 0x1480c0>
ran touchedBeach

所以请,我这几天一直在努力解决这个问题.我怎样才能使敲击的石头只调用touchedStone,而敲击的海滩只调用touchedBeach?我哪里错了?

So PLEASE, I've been trying to sort this for days. How do I make it so a tapped stone calls only touchedStone and a tapped beach calls only touchedBeach? Where am I going wrong?

推荐答案

在 iPhone OS 3.0 之前,UIScrollView 的 hitTest:withEvent: 方法总是返回 self 以便它直接接收 UIEvent,只有在当它确定它与滚动或缩放无关时.

Prior to iPhone OS 3.0, the UIScrollView's hitTest:withEvent: method always returns self so that it receives the UIEvent directly, only forwarding it to the appropriate subview if and when it determines it's not related to scrolling or zooming.

我无法对 iPhone OS 3.0 发表评论,因为它在 NDA 下,但请查看您的iPhone SDK Release notes for iPhone OS 3.0 beta 5":)

I couldn't really comment on iPhone OS 3.0 as it's under NDA, but check your "iPhone SDK Release notes for iPhone OS 3.0 beta 5" :)

如果您需要定位 3.0 之前的版本,您可以在 BeachView 中覆盖 hitTest:withEvent: 并设置一个标志以在 CGPoint 实际上位于石头中时忽略下一次海滩触摸.

If you need to target pre-3.0, you could override hitTest:withEvent: in BeachView and set a flag to ignore the next beach touch if the CGPoint is actually in a stone.

但是您是否尝试过简单地将对 [super touches*:withEvent:] 的调用从覆盖方法的末尾移到开头?这可能会导致先敲击石头.

But have you tried simply moving your calls to [super touches*:withEvent:] from the end of your overridden methods to the start? This might cause the stone tap to occur first.

这篇关于UIScrollView 触摸与子视图触摸的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

上一篇:如何使 UIScrollView 以一定的速度自动滚动? 下一篇:无限水平滚动 UIScrollView

相关文章

最新文章