7

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

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

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

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

但是,似乎两个视图都接受了点击并调用了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];
}

在石头.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

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


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

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

4

4 回答 4

3

是的,iPhone SDK 3.0 及更高版本,不要再将触摸传递给-touchesBegan:和 - touchesEnded:** UIScrollview**子类方法。你可以使用不一样的touchesShouldBegintouchesShouldCancelInContentView方法。

如果你真的想接触到这个,有一个允许这个的黑客。

在您的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超类的触摸。

于 2009-11-03T16:52:43.763 回答
2

在 iPhone OS 3.0 之前,UIScrollView 的 hitTest:withEvent: 方法总是返回 self 以便它直接接收 UIEvent,仅当它确定它与滚动或缩放无关时才将其转发到适当的子视图。

我无法真正评论 iPhone OS 3.0,因为它在 NDA 下,但请查看您的“iPhone SDK Release notes for iPhone OS 3.0 beta 5”:)

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

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

于 2009-05-18T14:23:20.177 回答
0

我对 a 有类似的问题,simpleView它被添加到 ascrollView中,每当我触摸 时simpleViewscrollView用于获取触摸的不是 simpleView,而是scrollView移动的。为避免这种情况,我禁用了scrollView用户触摸时的 srcolling,simpleView否则启用滚动。

- (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 ;

}
于 2013-11-19T05:52:40.503 回答
0

这可能与 iOS7 中的错误有关,请查看我的问题(已提交错误报告)

UIScrollView 子类在 iOS7 中改变了行为

于 2013-11-26T21:11:49.580 回答