How do I turn off interaction for a childnode?
I'm adding labels to a bunch of sprites, beneath the sprite, describing what they are. The sprites themselves are touchable, and have code that responds when touchesBegun etc.
The labels do not visually overlap the sprite, they're fully beneath the visual representation of the Sprites, but they are children of their respective Sprite, and I'd like to keep it that way.
But I don't want the labels to respond to touch.
I set the labels to
myLabel.isUserInteractionEnabled = false
But this doesn't make any difference, they're still responding to touch as if they're the Sprite.
By default isUserInteractionEnabled is false then the touch on a child like a SKLabelNode is, by default, a simple touch handled to the main (or parent) class (the object is here, exist but if you don't implement any action, you simply touch it)
If you set the userInteractionEnabled property to true on a subclassed SKNode then the touch delegates will called inside this specific class.
So, you can handle the touch for the label (as your case) within its class.
Related
I'm trying to geive the user the ability to drag a skspritenode over a UIImageView and UIButton, but whenever I create the scene it appears behind the UI elements. How do I fix this?
I am afraid that is just not possible. All the sprites and any other elements are rendered frame by frame on the SKScene node and cannot be "dragged" or placed anywhere else. These are not UIKit elements.
In this case, your view is acting as the SKScene and hence all the sprites are being rendered onto that.
SKView is a UIView/NSView in itself. All the Sprite Kit nodes (the scene is also a node) are constituents of the SKView and contained within it. You can only change the draw order of views but not their contents.
To give an example: what you're trying to do is the equivalent of trying to place a UIImageView on top of a UIButton's background but below the UIButton's label.
While technically you could achieve this for plain UIView elements with some trickery, the same will never work for Sprite Kit nodes. They aren't views to begin with but drawn onto an OpenGL framebuffer represented/managed by the SKView. From the perspective of Cocoa an SKView is a single view with no subviews in it.
Simply put: nodes are not views, and nodes are technically incompatible to views.
The UIImageView and its UIButton and whatever other content you want in there must be in a UIView that's sitting lower than the SKView you have the Sprite Kit contents in.
And you'll need to ensure the SKView is transparent (at least its background) and that it passes touches through to the UIView underneath if you need them down there sometimes.
I'm looking for help. I'm trying to make some puzzle game and I have thin scrollable layer at the bottom of my main layer which contains some puzzle shapes. I can scroll the layer and see every shape but shapes were positioned manually in code on the scrollable layer and the problem is, if I try to detect if I touched on sprite, which position is greater than 1024(in first iPad) it doesn't work. it doesn't work because touch can have position inside 1024X768 and the position of shape is for example 1500x100. to make it clearer, shapes are sprites and i try to detect them using CGRectContainsPoints method. Is there any other way to make it or have you any ideas? thanks in advance :]
What you could do is subclass your sprite, create a delegate for it and assign your main view/class as the delegate.
Implement the appropriate touch method, and send the message of what sprite was selected to your delegate (Main view or desired controller class).
With this every sprite has the same delegate, and sends a message to your controlling class as to what sprite has been selected and continue with desired functionality. No need for CGRectContainsPoint method.
This is cleaner, and more efficient.
Hope this helps!
I'm looking for a solution to help "pass" a touch gesture along.
Basically I have a menu, and I want users to be able to drag and drop items from the menu to the canvas in a single continuous drag.
I have already achieved a draggable image via pan gestures (we'll call these instances Sprites). I can also instantiate a Sprite anywhere on the UIView using a button or UIImageView with touch gestures.
However, this currently requires two touches. One to touch down the menu item button and release, creating the Sprite. The second to touch down on the sprite, allowing the user to drag it, and then release it where they want. I would like to merge these touches so that when a user touches a menu item, the Sprite is instantiated and already within the pan gesture, or something to that affect.
I've attached a visual description if that helps. Any help is appreciated. Thanks!
There is no way of artificially forcing UIGestureRecognizer to recognize touches that are passed to a different view.
From the Gesture Recognizer docs:
Delivery of events initially follows the usual path: from operating
system to the application object to the window object representing the
window in which the touches are occurring. But before sending an event
to the hit-tested view, the window object sends it to the gesture
recognizer attached to that view or to any of that view’s subviews.
Figure 3-1 illustrates this general path, with the numbers indicating
the order in which touches are received.
Figure 3-1
Event's delivery happens automaticaly by the system and is delivered to the appropriate view.
To do what you want I would implement the UIGestureRecognizer on the subview (view that contains your UIButton) and on press create an instance of your Sprite object and manipulate that object from withing the gesture recognizer of the subview. Alternatively you could use -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)even to reposition the object yourself.
I have an UILabel. I want to glow the touch area in it. That is, when I click on a point in that UILabel, a small circular portion around the touch point should be presented with glowing effect. How can get this?
Well you can do that by creating a CALayer or a CAGradientLayer based on how you want your glow and add it as a sublayer to the label's layer at the location of the touch.
For enabling the touch on UILabel, look at userInteractionEnabled property. You will need to set it to YES.
Then you will need to attach a UITapGestureRecognizer to the label for getting the tap. Once you have the touch location, add the custom glow layer as a subview to the label's layer in an invisible state. Animate the glow layer in and out. You might want to repeat a few times before removing the glow layer as a sublayer at completion.
UILabels don't respond to touches.
Use a UIButton with a custom type and provide images for the normal state and the (glowing) highlighted state.
Gesture recognizers are nice, but if you want to do something that starts when the finger touches, stops when the finger stops touching, and moves around with the finger in between, then it's hard to think of a good gesture recognizer for that. I think in that case you'd be better off just using touchesBegan, touchesMoved, and touchesEnded (don't forget touchesCancelled).
You can either put those methods on your view controller or subclass UILabel. Either way, set userInteractionEnabled = YES on the label.
As for how to graphically make that effect, I don't have any clever ideas for it at the moment.
Is it possible to make a UIView only appear inside a limited area of the screen, especially while animating? (When it reaches the boundary, it should simply cut off at the boundary point, as if it were being obscured by an object in front of it.) I need this because I have a roll-out menu comprised of UIButtons, and I don't want the menu to extend beyond the edge of the toolbar when closed. Thank you!
(Alternatively, hiding the entire UIView upon reaching the boundary would also be acceptable. I just don't know how to check for this condition without continuously querying the center property.)
You can define a clipping area for your UIVIew using the clipsToBounds property. If you are using CoreAnimation to animate your view, you may want to have a look a the maskToBounds property of CALayer objects as well (each UIVIew has a layer property of type CALayer).
From the UIView Class reference:
Normally, a subview’s visible area is
not clipped to the bounds of its
superview, but in iOS you can use the
clipsToBounds property to alter that
behavior.