当图层重叠时,如何将触摸处理限制为一个图层?

我有一个有趣的问题,在我正在编写的一个cocos2D程序中处理触摸事件。 我在CCScene中有3个CCLayer sublassed层:

backgroundLayer – z:0 – 用于显示背景图像的简单静态图层。

planetLayer – z:3 – 显示层 – 数据更改的可视化显示在这里。

gameControlsLayer – z:5 – 图层用于显示数据控制器,如滑块和button。

我分离了行星和控制层,因为我想平移和缩放行星层,而不用担心控制受到影响。

以下是设置这些图层的场景init代码:

- (id) init { self = [super init]; if (self != nil) { // background layer BackgroundLayer *backgroundLayer = [BackgroundLayer node]; [self addChild:backgroundLayer z:0]; // planet layer PlanetLayer *planetLayer = [PlanetLayer node]; [self addChild:planetLayer z:3]; // gameplay layer GameControlsLayer *gameControlsLayer = [GameControlsLayer node]; [self addChild:gameControlsLayer z:5]; } return self; } 

我需要在地球和控制层上的触摸处理。 在控制层上,触摸处理位于层次子控件对象内部。 我先写了所有这些代码,它工作正常。

在那之后,我为地球层写了全层的触摸处理,所以我可以触摸滚动和缩放。 我已经滚动(虽然不是缩放还没有),它工作正常。 我的问题是这样的:当我触摸和操作控制层上的控件时,它们工作的很好,但是当我上下滑动滑块时,例如,控制层后面的行星层仿佛触摸是为了它。

包含代码可能是多余的,但下面是相关的代码片段:

对于滑块控件,控件层的一个子对象:

 - (void) onEnterTransitionDidFinish { [[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:1 swallowsTouches:YES]; } - (void) onExit { [[CCTouchDispatcher sharedDispatcher] removeDelegate:self]; } #pragma mark Touch Delegate - (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event { CGPoint location = [[CCDirector sharedDirector] convertToGL:[touch locationInView:[touch view]]]; float distance = [self distanceBetweenPointOne:thumbPosition andPointTwo:location]; if (distance > thumbRadius*2) { return NO; } // touch is on the thumb. store the location so we // can calculate changes on ccTouchMoved events touched = YES; return YES; } - (void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event { if (!touched) { return; } CGPoint location = [[CCDirector sharedDirector] convertToGL:[touch locationInView:[touch view]]]; location = [self convertToNodeSpace:location]; // if we're too far off the thumb, abandon it float distance = [self distanceBetweenPointOne:thumbPosition andPointTwo:location]; if (distance > thumbRadius*3) { //touched = NO; return; } // this call adjusts some ivars – not relevant [self updateValueAndPosition:location]; } - (void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event { if (touched) { touched = NO; } } - (void)ccTouchCancelled:(UITouch *)touch withEvent:(UIEvent *)event { [self ccTouchEnded:touch withEvent:event]; } 

以下是来自地球层的相关代码:

 // Yes, we want touch notifications please // - (void) onEnterTransitionDidFinish { [[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:NO]; } #pragma mark Touch Delegate - (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event { CGPoint touchLocation = [touch locationInView:[touch view]]; touchLocation = [[CCDirector sharedDirector] convertToGL:touchLocation]; // ****NOTE – the following is a kludge I used it to break // ********** the behavior; the controls are all grouped // ********** at the bottom of the screen. But this is not // ********** an acceptable fix. I shouldn't need to mask // ********** off certain areas of the screen. This strategy // ********** will not hold once I add other controls to the // ********** control layer. // if (touchLocation.y > 250.0f) { self.touched = YES; touchHash = [touch hash]; return YES; } return YES; } - (void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event { if (!touched) { return; } if ([touch hash] == touchHash) { CGSize screenSize = [[CCDirector sharedDirector] winSize]; CGPoint touchLocation = [touch locationInView:[touch view]]; CGPoint prevLocation = [touch previousLocationInView:[touch view]]; touchLocation = [[CCDirector sharedDirector] convertToGL:touchLocation]; prevLocation = [[CCDirector sharedDirector] convertToGL:prevLocation]; CGPoint diff = ccpSub(touchLocation, prevLocation); CGPoint currentPosition = [self position]; CGPoint newPosition = ccpAdd(currentPosition, diff); if (newPosition.x < lowestX) newPosition.x = lowestX; else if (newPosition.x > highestX-screenSize.width) newPosition.x = highestX-screenSize.width; if (newPosition.y < lowestY) newPosition.y = lowestY; else if (newPosition.y > highestY-screenSize.height) newPosition.y = highestY-screenSize.height; [self setPosition:newPosition]; } } - (void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event { if ([touch hash] == touchHash) { if (touched) { touched = NO; } } } - (void)ccTouchCancelled:(UITouch *)touch withEvent:(UIEvent *)event { [self ccTouchEnded:touch withEvent:event]; } 

我想添加捏缩放function,但我需要清除这个问题之前,这将是明智的。 有人在这里有答案吗? 我觉得我失去了一些明显的东西…

谢谢!

在您的planetLayerccTouchBegan: ,您应该find一种方法来判断触摸是否在某个控件的内部,并且在这种情况下返回NO而不是YES。

你有一个可能性是检查[touch view] (我有一个控制层由UIKit对象,它的工作原理是这样的),否则你应该得到触摸的坐标,并检查他们是否CGRectContainsPoint([control rect], location))