I have a simple full screen UIView . When the user taps on the screen, I need write out the x,y
Console.WriteLine ("{0},{1}",x,y);
What API Do i need to use for that?
In MonoTouch (since you asked in C#...although the previous answer is correct :) that would be:
public override void TouchesBegan (NSSet touches, UIEvent evt)
{
base.TouchesBegan (touches, evt);
var touch = touches.AnyObject as UITouch;
if (touch != null) {
PointF pt = touch.LocationInView (this.View);
// ...
}
You could also use a UITapGestureRecognizer:
var tapRecognizer = new UITapGestureRecognizer ();
tapRecognizer.AddTarget(() => {
PointF pt = tapRecognizer.LocationInView (this.View);
// ...
});
tapRecognizer.NumberOfTapsRequired = 1;
tapRecognizer.NumberOfTouchesRequired = 1;
someView.AddGestureRecognizer(tapRecognizer);
Gesture recognizers are nice as they encapsulate touches into reusable classes.
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
printf("Touch at %f , %f \n" , [touch locationInView:self.view].x, [touch locationInView:self.view].y);
}
Related
I'm trying to detect when one node overlaps another. I am teaching myself sprite kit and cannot get intersectsNodes to give any output. I've loaded 2 nodes that can be moved around on the screen and then added intersectsNodes in the update section.
-(void)update:(CFTimeInterval)currentTime {
SKSpriteNode* playerShip1;
SKSpriteNode* playerShip2;
if ([playerShip1 intersectsNode: playerShip2]) {
NSLog(#"your ships overlap");
}
Any thoughts on why no intersection is found?
here is the whole m file.
#import "MyScene.h"
#implementation MyScene
-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
SKSpriteNode* playerShip1 = [SKSpriteNode spriteNodeWithImageNamed:#"player"];
playerShip1.position = CGPointMake(self.frame.size.width/2, playerShip1.frame.size.height);
playerShip1.name = #"PLAYER_SHIP_1";
[self addChild:playerShip1];
SKSpriteNode* playerShip2 = [SKSpriteNode spriteNodeWithImageNamed:#"player"];
playerShip2.position = CGPointMake(self.frame.size.width/2, self.frame.size.height-playerShip2.frame.size.height);
playerShip2.name = #"PLAYER_SHIP_2";
[self addChild:playerShip2];
SKSpriteNode* playerShip3 = [SKSpriteNode spriteNodeWithImageNamed:#"player"];
playerShip3.position = CGPointMake(self.frame.size.width/2, self.frame.size.height/2);
playerShip3.name = #"PLAYER_SHIP_3";
[self addChild:playerShip3];
activeDragNode = nil;
}
return self;
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
// Identify where this touch is on the scene
CGPoint scenePosition = [touch locationInNode:self];
// Find the child node that contains this touch
SKNode* checkNode = [self nodeAtPoint:scenePosition];
// Make sure it is a player ship and not another node like the parent SKScene
if (checkNode && [checkNode.name hasPrefix:#"PLAYER_SHIP"]) {
activeDragNode = (SKSpriteNode*)checkNode;
SKAction *zoomAction = [SKAction scaleTo:1.5 duration:.2];
[checkNode runAction:zoomAction];
//NSLog(#"your ship has been hit!");
}
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
// Remove reference to which object we are dragging
activeDragNode=nil;
UITouch *touch = [touches anyObject];
CGPoint scenePosition = [touch locationInNode:self];
SKNode* checkNode = [self nodeAtPoint:scenePosition];
SKAction *shrinkAction = [SKAction scaleTo:1.0 duration:.2];
[checkNode runAction:shrinkAction];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
// Be sure we have a reference to an object to drag
if (activeDragNode==nil) return;
UITouch *touch = [touches anyObject];
CGPoint scenePosition = [touch locationInNode:self];
CGPoint lastPosition = [touch previousLocationInNode:self];
// Calculate the new location of the dragged node
CGPoint newLoc = CGPointMake(activeDragNode.position.x + (scenePosition.x - lastPosition.x), activeDragNode.position.y + (scenePosition.y - lastPosition.y));
// Update this location
activeDragNode.position = newLoc;
}
-(void)update:(CFTimeInterval)currentTime {
SKSpriteNode* playerShip1;
SKSpriteNode* playerShip2;
if ([playerShip1 intersectsNode: playerShip2]) {
NSLog(#"your ships overlap");
}
/* Called before each frame is rendered */
}
#end
First you need to set a position for each node:
playerShip1.position = CGPointMake(0,0);
Second you need to add each node to the view:
[self addChild:playerShip1];
Also, you are adding the nodes in your update method which is the wrong place. As your code is now, you will continuously add each node 60 times a second.
I see you adding additional code. You are creating 3 SKSpriteNodes in your init method which is fine and works. However, you are not keeping a reference to these 3 nodes. This means once they are created, you have no way to access them again. To resolve this, you should create 3 SKSpriteNode class properties or add all 3 nodes into an array (class property for the array). If you don't know what I mean, that's ok, it just means you have a ways to learn.
I suggest you do a couple of tutorials as this will teach some additional fundamentals and prevent a ton of "why isn't this working" frustration in the future.
I created a sknodeshape. How can I detect if the shape I made was touched(clicked)?
Here is the code: (I solved it already)
//metung_babi is the name of the SKShapeNode
UITouch *touch = [touches anyObject];
CGPoint nokarin = [touch locationInNode:self];
SKNode *node = [self nodeAtPoint:nokarin];
if ([node.name isEqualToString:#"metung_babi"]) {
NSlog(#"touch me not");
}
my mistake was when I created the shape I put the SKShapeNode name before initializing it.
Implement the touch delegate methods. Then, in the -touchesBegan: method, extract the point of touch and retrieve the node using the [self nodeAtPoint:] method
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
/* Called when a touch begins */
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInNode:self];
SKNode *yourNode = ....;
CGRect yourNodeFrame = bowlNode.frame;
if (CGRectContainsPoint(yourNodeFrame, location)) {
//your node may be touched, check if it's your node
SKNode *theNode = [self nodeAtPoint:location];
if ([theNode.name isEqualTo:yourNode.name]) {
//it's your node touched
}
}
}
the method nodeAtPoint return value is complicated. you can check the document to find different situations
I am sure that this problem will be easily resolved however I am relatively new to iOS development. I am trying to handle passing touch events to children that are lower in the draw order on a UIView. For example -
I create extended UIImageView to create my MoveableImage class. This class is just basically UIImageView that implements the touchesBegan,touchesEnded and touchesMoved-
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self showFrame];
//if multitouch dont move
if([[event allTouches]count] > 1)
{
return;
}
UITouch *touch = [[event touchesForView:self] anyObject ];
// Animate the first touch
CGPoint colorPoint = [touch locationInView:self];
CGPoint touchPoint = [touch locationInView:self.superview];
//if color is alpha of 0 , they are touching the frame and bubble to next responder
UIColor *color = [self colorOfPoint:colorPoint];
[color getRed:NULL green:NULL blue:NULL alpha:&touchBeganAlpha];
NSLog(#"alpha : %f",touchBeganAlpha);
if(touchBeganAlpha > 0)
{
[self animateFirstTouchAtPoint:touchPoint];
}
else {
[super.nextResponder touchesBegan:touches withEvent:event];
}
}
So the end result is basically this- If they are touching the frame of the imageView and not the image inside the other image that will be underneath can possibly respond. See this image for an example.
So far I have tried next responder however that does not solve the problem. Any help would be greatly appreciated!
Resolved- I stopped checking the alpha on the touchesBegan and touchesMoved. Ovveriding pointInside allowed the UIView to handle that for me.
-(BOOL) pointInside:(CGPoint)point withEvent:(UIEvent *) event
{
BOOL superResult = [super pointInside:point withEvent:event];
if(!superResult)
{
return superResult;
}
if(CGPointEqualToPoint(point, self.previousTouchPoint))
{
return self.previousTouchHitTestResponse;
}else{
self.previousTouchPoint = point;
}
BOOL response = NO;
//if image is nil then return yes and fall back to super
if(self.image == nil)
{
response = YES;
}
response = [self isAlphaVisibleAtPoint:point];
self.previousTouchHitTestResponse = response;
return response;
}
You can override instead - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event method for your subclass of UIImageView. (It is a method of uiview that each subclass can override)
The UIView uses this method in hitTest:withEvent: to determine which subview should receive a touch event. If pointInside:withEvent: returns YES, then the subview’s hierarchy is traversed; otherwise, its branch of the view hierarchy is ignored.
Check the source code on github of OBShapedButton. They handle tap event only for the opaque part of a button.
I have a view control and inside I plan to place some controls like buttons textbox etc... I can drag my view along the x axis like:
1)
2)
with the following code:
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [[event allTouches] anyObject];
if( [touch view] == ViewMain)
{
CGPoint location = [touch locationInView:self.view];
displaceX = location.x - ViewMain.center.x;
displaceY = ViewMain.center.y;
startPosX = location.x - displaceX;
}
CurrentTime = [[NSDate date] timeIntervalSince1970];
}
- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [[event allTouches] anyObject];
if( [touch view] == ViewMain)
{
CGPoint location = [touch locationInView:self.view];
location.x =location.x - displaceX;
location.y = displaceY;
ViewMain.center = location;
}
}
-(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
double time = [[NSDate date] timeIntervalSince1970]-CurrentTime;
UITouch *touch = [[event allTouches] anyObject];
if( [touch view] == ViewMain)
{
CGPoint location = [touch locationInView:self.view];
location.x =location.x - displaceX;
location.y = displaceY;
ViewMain.center = location;
double speed = (ViewMain.center.x-startPosX)/(time*2);
NSLog(#"speed: %f", speed);
}
}
not that I have to add the global variables:
float displaceX = 0;
float displaceY = 0;
float startPosX = 0;
float startPosY = 0;
double CurrentTime;
the reason why I created those variables is so that when I start dragging the view the view moves from the point where I touch it instead of from the middle.
Anyways if I touch a button or image the view will not drag even though the images have transparency on the background. I want to be able to still be able to drag the view regardless if there is an image on top of the view. I where thinking that maybe I need to place a large transparent view on top of everything but I need to have buttons, images etc. I want to be able to drag a view just like you can with:
note that I was able to drag the view regardless of wither I first touched an app/image or text. How could I do that?
I think your problem is that if you touch a UIButton or a UIImageView with interaction enabled, it doesn't pass the touch along.
For the images, uncheck the User Interaction Enabledproperty in IB.
For the buttons that are causing touchesBegan:withEvent:, etc. to not get called, then look at the following link: Is there a way to pass touches through on the iPhone?.
You may want to consider a different approach to this problem. Rather than trying to manually manage the content scrolling yourself you would probably be better off using a UIScrollView with the pagingEnabled property set to YES. This is the method Apple recommends (and it's probably the method used by Springboard.app in your last screenshot). If you are a member of the iOS developer program check out the WWDC 2010 session on UIScrollView for an example of this. I think they may have also posted sample code on developer.apple.com.
I am having 2 imageviews with image in it. I want that when I click on the first image the image should get selected and if it is selected it should return me value TRUE or 1 that should be saved in sqlite database. How is this possible?
By using UITouch class methods you will get which image view is touched, or you can put imageview inside button then you will get click event.
You go with Touch events.Capture the touch points and perform your actions.Here I will give u a sample structure to do this,
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
CGPoint location= [touch locationInView:self.view];
if(CGRectContainsPoint(firstImage.frame, location)) {
//set some flag like
selectionFlag=1; }
else if(CGRectContainsPoint(secImage.frame, location)){
selectionFlag=2; }
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView:self.view];
if(CGRectContainsPoint(firstImage.frame, location)) {
if(selectionflag==1) {
//do ur db actions }
}
else if(CGRectContainsPoint(secImage.frame, location)) {
if(selectionflag==2) {
//do ur db actions }
}
selectionflag=0;
}
first do
[self.*yourimageViewname* setUserEnteractionEnabled:YES];
BOOL select1,secelect2;
select1=NO;
select2=NO;
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch=[touches anyObject];
CGPoint touchLocation = [touch locationInView:touch.view];
//give the beginning and ending x and y points in condition to check which imageView is taped
if(touchLocation.x>1 && touchLocation.x<116 && touchLocation.y>133 && touchLocation.y<233)
{
select1=YES;
}
else if(touchLocation.x>120 && touchLocation.x<300 && touchLocation.y>133 && touchLocation.y<233)
{
select2=YES;
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
}
On the condition which boolean variable is true you can save or whatever you want to do further coding your application.
Using the touches is one way as explained in the answers below. If you have just two imageview you can also try to have two custom transparent buttons on top of that imageview and therefore you can easily know which image is touched based on the tag you give for the buttons.
What you could also do is create two buttons (instead of UIImageViews) that have images. They should display roughly the same (you could even disable the touch states, etc). And you get UIResponder events for free (as in; you can target the action to a selector).
UPDATE: here's roughly how (didn't bother configuring the buttons though).
UIButton *button1 = [UIButton buttonWithType:UIButtonTypeCustom];
[button1 setImage:yourImage forState:UIControlStateNormal];
[button1 addTarget:self action:#selector(buttonTouched:) forControlEvents:UIControlEventTouchUpInside];
// .. now create a second button .. //
And your button will go to the following method when touched:
- (void)buttonTouched:(id)sender
{
// .. add your stuff to your database .. //
// .. you can identify your button by sender, or give the button a tag (number) to identify it .. /
}