Cocos2d and UISCrollview pass through touches - uiscrollview

I have made a CCNode which I dubbed ScrollNode, basically it is a CCNode which crops a certain region of a child node, and this child node is moving on it's x and y position based on the scroll location of a transparent overlaying UIScrollView.
I wanted a ScrollView in Cocos2d which felt native to the iOS platform and it does a good job.
However a problem arises with this way of handeling things. The touches for CCButton on a node which can be scrolled are not called (because there is a transparent UIScrollView over that region) is it possible to pass through the touches from the UIScrollView when it is a "tap" gesture and not a "pan gesture"
I have tried the following:
// Make sure touches are passed trough all views
for(UIGestureRecognizer *recognizer in self.scrollView.gestureRecognizers)
{
recognizer.cancelsTouchesInView = NO;
}
But this doesn't seem to make any difference.
Kind Regards,

The way I prefer to solve this is to set up my own UITapGestureRecognizer on the UIScrollView instance. The handler then just passes the touch location to the code that handles taps in my scene.
The tap and pan gesture recognizers know how to interact with each other so it still provides the native experience.

Seems like I've fixed it. I have subclassed the UIScrollView, and passed the touches* events to it's parent. Which seems to have no effect on the scrolling, but makes sure it does trigger the tap event for CCButtons.
#import "ScrollNodeScrollView.h"
#implementation ScrollNodeScrollView
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
[self.superview touchesCancelled:touches withEvent:event];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self.superview touchesBegan:touches withEvent:event];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
[self.superview touchesMoved:touches withEvent:event];
}
- (void)touchesEnded:(NSSet *)aTouches withEvent:(UIEvent *)anEvent
{
[self.superview touchesEnded:aTouches withEvent:anEvent];
}
#end

Related

NSOutlineView scroll animation is not working

I want to remove the NSOutlineView's show/hide button.So,I override the NSOutlineView and get the mouseDown event.The follow is the code.
-(void)mouseDown:(NSEvent *)theEvent
{
NSLog(#"LeftFolderListOutlineView mouseDown");
[super mouseDown:theEvent];
NSPoint localPoint = [self convertPoint:theEvent.locationInWindow
fromView:nil];
NSInteger row = [self rowAtPoint:localPoint];
id clickedItem = [self itemAtRow:row];
if (![clickedItem isKindOfClass:[NSDictionary class]]) {
return;
}
if ([self isItemExpanded:clickedItem]) {
[[self animator] collapseItem:clickedItem];
}else{
[[self animator] expandItem:clickedItem];
}
}
It should be a scroll animation when the NSOutlineView collapse or expand.But in this case it's not working.Anyone tell me why and how can I improve this?
To remove 'show/hide button' (outline cell) you could implement - (NSRect)frameOfOutlineCellAtRow:(NSInteger)row method in the NSOutliveView subclass and return NSZeroRect.
NSOutlineView collapse/expand animation is not animatable via animator.
Only OS 10.7 or above provide collapse/expand animation effects. So it you planed to support older OS versions you need to provide separate implementation.
If you want to provide collapse/expand animation on OS 10.6 or below, you definitely needed to override 'drawRect' of NSOutlineView.
-- Update --
Sorry, I think I neglected the main point. 10.7 expand/collapse animation is automatically kick in only when users clicked the outline cell. If we want to show the animation without default outline cells, there is no other way but manually implementing animation effects, I think.
I made a sample project that implement expand/collapse animation effects with image drawing.
Check the source codes in here: https://github.com/roh0sun/ovanimation

NSEventPhaseEnded not called on NSScrollView with IKImageBrowserView

I have an IKImageBrowserView embedded within an NSScrollView, to help test this problem the IKImageBrowserView only fills half the of width of the NSScrollView.
My NSScrollView subclass implements the following method and logs when a scroll began and ended on the scrollview.
- (void)scrollWheel:(NSEvent *)event {
switch (event.phase) {
case NSEventPhaseBegan:
NSLog(#"NSEventPhaseBegan");
break;
case NSEventPhaseEnded:
NSLog(#"NSEventPhaseEnded");
break;
}
[super scrollWheel:event];
}
The NSEventPhaseBegan event phase successfully calls whether the cursor is over the IKImageBrowserView or not when you start scrolling. This is the expected behaviour.
But NSEventPhaseEnded event phase is not called when the cursor is over the IKImageBrowserView when you stop scrolling. If the cursor is not over the IKImageBrowserView then NSEventPhaseEnded does get called.
Why is the IKImageBrowserView preventing NSEventPhaseEnded being called on my NSScrollView?
Spoke to a helpful engineer at Apple who told me this behaviour is in fact a bug. ImageKit is eating some scrollWheel events unfortunately. As a workaround, subclass the IKImageBrowserView, implement scrollWheel and forward the event both to "super" and the enclosing scrollview.
#implementation MyImageBrowserView
- (void)scrollWheel:(NSEvent *)theEvent {
[super scrollWheel:theEvent];
if ([theEvent phase] == NSEventPhaseEnded)
[[self enclosingScrollView] scrollWheel:theEvent];
}
}
#end

Dragging two images using multi touch

I am fairly new to touch event and i have a problem. I use the code above to drag two images on screen. The code works however when the the second finger touches the screen the first movement stops. So, the problem is related to multi-touch. I also, do not know how to calculate the second touches co-ordinates. I enabled multitouch in the view and in both images. I would be great full if somebody could help me move each image with each finger.
Thanks in advance!
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView:self.view];
if ([touch view] == image) {
image.center = location;
} else if ([touch view] == image2) {
image2.center = location;
}}
-(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
[self touchesBegan:touches withEvent:event];}
I would recommend using a custom UIGestureRecognizer for that. It will give you an nice encapsulated way to manage what you want. Dragging two images at the same time is in essence a gesture.

Can't figure out iPad landscape view coordinates

Being new to objective-C but tinkering I was trying out dragging with the iPad, and the following code from my viewcontroller.m works okay in portrait, but not in landscape:
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView:mainView.superview];
testViewToMove.center = location;
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
[self touchesBegan:touches withEvent:event];
}
mainView being the default view that was created with the app, and testViewToMove being a UIView I made for kicks.
In landscape, the coordinates don't seem to translate. I'm sure this is something obvious, but I don't get it, what's going on here?
I tried setting the view to landscape, and tinkering with some other settings to no avail... I also saw this, but to my own dismay I haven't been able to get it to work.
Seems I just needed to change mainView.superview to self.view in the first method, after applying the fix linked above.

simple way to recognize/identify a gesture

Hi I implemented this function and i can hand the gestures but how can i recognize what gesture is which?for example simple move to left or right?
my code for handling:
/*this function is made to handel finger gesture and flip the view to other account*/
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
FirstViewController *screen = [[FirstViewController alloc] initWithNibName:nil bundle:nil];
screen.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
screen.myArray = myArray;
[self presentModalViewController:screen animated:YES];
[screen release];
}
Thanks for any answer
Well, it very much depends on what gesture you want to trap. If it is a simple pinch, swipe tap etc then you should probably use one of Apple new (in 3.2) convenience classes described in this document.
Using these, trapping a gesture is as simple as adding something like the following to your code:
UITapGestureRecognizer *doubleFingerDTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleDoubleDoubleTap:)];
doubleFingerDTap.numberOfTapsRequired = 2;
[self.view addGestureRecognizer:doubleFingerDTap];
and then implementing the method to process the gesture when it is found:
- (void)handleDoubleDoubleTap:(UIGestureRecognizer *)sender {
//Do something here
}
This will trap a double tap.

Resources