Making images appear... How? - iphone

Could someone please tell me how to make an image appear when the user taps the screen and make it appear at the position of the tap.
Thanks in advance,
Tate

UIView is a subclass of UIResponder, which has the following methods that might help: -touchesBegan:withEvent:, -touchesEnded:withEvent:, -touchesCancelled:withEvent: and -touchesMoved:withEvent:.
The first parameter of each of those is an NSSet of UITouch objects. UITouch has a -locationInView: instance method which should yield the position of the tap in your view.

You could create an initial star and just move it every time view is touched.
I'm not sure what you're end result will look like.
Note:
This code will give you 1 star that moves with a tap
Here is my code:-
(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
NSSet *allTouches = [event allTouches];
switch ([allTouches count]) {
case 1:
{
UITouch *touch = [[allTouches allObjects] objectAtIndex:0];
CGPoint point = [touch locationInView:myView];
myStar.center = point;
break;
}
default:
break;
}
}

It seems implied from the question that you want the user to be able to tap anywhere on the screen and have an image drawn where they tap? As opposed to tapping in a designated place and having the image appear there?
If so, you're probably going to have to go with a custom view. In that case, you'd do something like the following:
Create a subclass of UIView.
Override the touchesBegan method. Call [[touches anyObject] locationInView:self] (where touches is the first argument to the method, an NSSet of UITouch objects) to get the location of the touch, and record it.
Override the touchesEnded method. Determine the location touches ended at using the same method as in step 2.
If the second location is near the first, you'll want to place your image at that location. Record that location and call [self setNeedsDisplay] to cause the custom view to be redrawn.
Override the drawRect method. Here, if the location has been set in step 4, you can use the UIImage method drawAtPoint to draw your image at the selected location.
For further details, this link might be worth a look. Hope that helps!
EDIT: I've notice you've asked essentially the same question before. If you're not happy with the answers given there, it's generally considered better to "bump" the old one, perhaps by editing it to ask for further clarification, rather than create a new question.
EDIT: As requested, some very brief sample code follows. This is probably not the best code around, and I haven't tested it, so it may be a little iffy. Just for clarification, the THRESHOLD allows the user to move their finger a little while tapping (up to 3px), because it's very difficult to tap without moving your finger a little.
MyView.h
#define THRESHOLD 3*3
#interface MyView : UIView
{
CGPoint touchPoint;
CGPoint drawPoint;
UIImage theImage;
}
#end
MyView.m
#implementation MyView
- (id) initWithFrame:(CGRect) newFrame
{
if (self = [super initWithFrame:newFrame])
{
touchPoint = CGPointZero;
drawPoint = CGPointMake(-1, -1);
theImage = [[UIImage imageNamed:#"myImage.png"] retain];
}
return self;
}
- (void) dealloc
{
[theImage release];
[super dealloc];
}
- (void) drawRect:(CGRect) rect
{
if (drawPoint.x > -1 && drawPoint.y > -1)
[theImage drawAtPoint:drawPoint];
}
- (void) touchesBegan:(NSSet*) touches withEvent:(UIEvent*) event
{
touchPoint = [[touches anyObject] locationInView:self];
}
- (void) touchesEnded:(NSSet*) touches withEvent:(UIEvent*) event
{
CGPoint point = [[touches anyObject] locationInView:self];
CGFloat dx = point.x - touchPoint.x, dy = point.y - touchPoint.y;
if (dx + dy < THRESHOLD)
{
drawPoint = point;
[self setNeedsDisplay];
}
}
#end

Related

Continuous Touching on a ccMenuItem

I am creating a program with cocos2d where I have 2 ccMenuItems each linked to an image: In this case, one is a left arrow, the other is a right arrow. I also have an image in the center of my view that will rotate depending on the arrow pressed.
When I put my finger on one of the two menu items, either left or right, I want the center image to rotate as long as my finger is on the button. That is where I got lost. I tried using the following code:
- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event {
CGPoint p = [touch locationInView:[touch view]];
if (CGRectContainsPoint(leftArrow, p) || CGRectContainsPoint(rightArrow, p)) {
return YES;
}
return NO;
}
- (void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event {
CGPoint p = [touch locationInView:[touch view]];
if (CGRectContainsPoint(leftArrow, p)) {
[gun runAction:[CCRepeatForever actionWithAction:[CCRotateTo actionWithDuration:0.2 angle:180]]];
}
if (CGRectContainsPoint(rightArrow, p)) {
[gun runAction:[CCRepeatForever actionWithAction:[CCRotateTo actionWithDuration:0.2 angle:0]]];
}
}
Using this code, when I press on one of the two menu items, the ccTouchBegan method isn't even called. The method is only called when I touch elsewhere.
How do I work with continuous actions when holding down a ccMenuItem.
Thank you for your help!
You have to subclass CCMenuItem to get such behaviour:
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
#interface RepeatMenuItem : CCMenuItemSprite
{
CGFloat speed;
}
#end
And implementation:
////////////////////////////////////////////////////////////////////
// RepeatMenuItem
////////////////////////////////////////////////////////////////////
#pragma mark -
#pragma mark RepeatMenuItem
#implementation RepeatMenuItem
-(void) selected
{
[super selected];
block_(self);
speed = 0.8;
[self schedule:#selector(repeatEvent:) interval:speed];
}
-(void) unselected
{
[self unschedule:#selector(repeatEvent:)];
[super unselected];
}
-(void) activate
{
}
-(void) repeatEvent:(id)sender
{
CGFloat minSpeed = 0.05;
if (speed > minSpeed)
speed = speed/3;
if (speed < minSpeed)
speed = minSpeed;
[self unschedule:#selector(repeatEvent:)];
block_(self);
[self schedule:#selector(repeatEvent:) interval:speed];
}
#end
As I understand, two methods you posted are in your CCLayer's subclass.
First of all, if you want to handle touches by yourself, you must remove menu items. CCMenu has much more touch priority and if it handles that the touch hit any menu item, it will swallow it. Thats why you receive touches only when touch is outside menu items.
The second one, what is leftArrow and rightArrow? Rects of your arrows?
And as for me, in such case I can propose you to run update method and change rotation property of your center image in it on every tick. I mean, that rotation value will be 0 if no one arraw was touched and will have positive or negative value due to the arrow you touched.
You can extend the CCMenuItemWhatever class you are using for these menu items, and override the 'selected' and 'unselected' methods. The menu grabs the touches (ie IT answers YES on its own ccTouchBegan function, thus the touch dispatcher does not propagate it to you).
-(void) selected{
[super selected];
// start your animation here
}
-(void) unselected {
[super unselected];
// stop your animation here.
}

Passing touch to next responder or other sub-view iOS

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.

Dragging a specific UIImageView

In my code I have an array of objects which are UIImageViews with UIImages in them.
I use a for loop in -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event to move all objects from the array one by one.
Once they are moved to different positions on the main view I would like to be able to grab any of those objects and move them somewhere else.
I'm not sure how best to do this. Is there a way I can use touchesbegin so that I can drag only the item I clicked on?
Basically, there are five UIImageViews there now and each one has UIImage and I am trying to get to the point where when i click on any of them they are able to move around.
EDIT: John Muchow posted this on a blog here. You should be able to adapt for your own purposes.
//UIDraggableImageView.h
#import <UIKit/UIKit.h>
#interface UIDraggableImageView : UIImageView
{
CGPoint currentPoint;
}
#end
//UIDraggableImageView.m
#import "UIDraggableImageView.h"
#implementation UIDraggableImageView
- (id)initWithImage:(UIImage *)image
{
if (self = [super initWithImage:image]) {
self.userInteractionEnabled = YES;
}
return self;
}
-(void)dealloc {
[super dealloc];
}
- (void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
{
// When a touch starts, get the current location in the view
currentPoint = [[touches anyObject] locationInView:self];
}
- (void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
{
// Get active location upon move
CGPoint activePoint = [[touches anyObject] locationInView:self];
// Determine new point based on where the touch is now located
CGPoint newPoint = CGPointMake(self.center.x + (activePoint.x - currentPoint.x),
self.center.y + (activePoint.y - currentPoint.y));
//--------------------------------------------------------
// Make sure we stay within the bounds of the parent view
//--------------------------------------------------------
float midPointX = CGRectGetMidX(self.bounds);
// If too far right...
if (newPoint.x > self.superview.bounds.size.width - midPointX)
newPoint.x = self.superview.bounds.size.width - midPointX;
else if (newPoint.x < midPointX) // If too far left...
newPoint.x = midPointX;
float midPointY = CGRectGetMidY(self.bounds);
// If too far down...
if (newPoint.y > self.superview.bounds.size.height - midPointY)
newPoint.y = self.superview.bounds.size.height - midPointY;
else if (newPoint.y < midPointY) // If too far up...
newPoint.y = midPointY;
// Set new center location
self.center = newPoint;
}
#end
I've done something similar with great success using the UIPanGestureRecognizer in my draggable view. To hook it up, it might look something like this:
#implementation DraggableView
-(id)initWithFrame:(CGRect)frame
{
...
...
UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(pan:)] autorelease];
[self addGestureRecognizer:panGesture];
..
return self;
}
#end
In your pan: method, you could check the state of the gesture and even capture the gesture's location and use it to relocate your view. Here's a rough example of what it might look like:
-(void)pan:(UIPanGestureRecognizer *)gesture
{
if (gesture.state==UIGestureRecognizerStateChanged)
{
//We're moving!
UIView *aRootView = <perhaps your root view controller's view>;
CGPoint currentOrigin = [gesture translationInView:aRootView];
self.frame = CGRectMake(currentOrigin.x,currentOrigin.y,self.frame.size.width,self.frame.size.hight);
...
...
}
}
Here is more reading on the UIPanGestureRecognizer.
You might want to consider adding gesture recognizers to the views that you want to move, that way you can easily tell when they are tapped and you can use touchesMoved to move them around...
On a button click add an image from camera roll to the imageview. Image can zoom in and out and should drag that image to any place in the view.

Help with Subclass Property

I have a UIView subclass called Card that I move around on my board and drop on hot spots called slots. When I drop the card I use the hitTest to figure out if I am dropping the card on one of my hotspots. I want to get a property of that hot spot but I am having trouble getting that to work properly. My only guess is the hitTest returns a UIView and my hot spot is a UIView subclass. The error I get is "Request for member 'slotIndex' in something not a structure or union"
Here is the TouchesEnded method I am using from my Card Class
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent*)event {
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:self.superview];
[self setUserInteractionEnabled:NO];
UIView *backView = [self.superview hitTest:location withEvent:nil];
if ([backView isKindOfClass:[CardSlot class]]) {
self.center = backView.center;
NSLog(#"Slot Number: %#", backView.slotIndex);
} else {
//Move it back to the top corner
self.center = CGPointMake(50,50);
}
[self setUserInteractionEnabled:YES];
}
My question is how do I go about testing if I am in a slot hot spot and then get the properties of that slot (UIView Subclass)?
To help the compiler, you need to cast the pointer to a CardSlot after determining that it is one. This way the compiler can know about the slotIndex property. For example:
if ([backView isKindOfClass:[CardSlot class]]) {
CardSlot *cardSlot = (CardSlot *)backView;
// From here you can access cardSlot.slotIndex
}

Making a UIImageView appear when screen is tapped [duplicate]

Could someone please tell me how to make an image appear when the user taps the screen and make it appear at the position of the tap.
Thanks in advance,
Tate
UIView is a subclass of UIResponder, which has the following methods that might help: -touchesBegan:withEvent:, -touchesEnded:withEvent:, -touchesCancelled:withEvent: and -touchesMoved:withEvent:.
The first parameter of each of those is an NSSet of UITouch objects. UITouch has a -locationInView: instance method which should yield the position of the tap in your view.
You could create an initial star and just move it every time view is touched.
I'm not sure what you're end result will look like.
Note:
This code will give you 1 star that moves with a tap
Here is my code:-
(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
NSSet *allTouches = [event allTouches];
switch ([allTouches count]) {
case 1:
{
UITouch *touch = [[allTouches allObjects] objectAtIndex:0];
CGPoint point = [touch locationInView:myView];
myStar.center = point;
break;
}
default:
break;
}
}
It seems implied from the question that you want the user to be able to tap anywhere on the screen and have an image drawn where they tap? As opposed to tapping in a designated place and having the image appear there?
If so, you're probably going to have to go with a custom view. In that case, you'd do something like the following:
Create a subclass of UIView.
Override the touchesBegan method. Call [[touches anyObject] locationInView:self] (where touches is the first argument to the method, an NSSet of UITouch objects) to get the location of the touch, and record it.
Override the touchesEnded method. Determine the location touches ended at using the same method as in step 2.
If the second location is near the first, you'll want to place your image at that location. Record that location and call [self setNeedsDisplay] to cause the custom view to be redrawn.
Override the drawRect method. Here, if the location has been set in step 4, you can use the UIImage method drawAtPoint to draw your image at the selected location.
For further details, this link might be worth a look. Hope that helps!
EDIT: I've notice you've asked essentially the same question before. If you're not happy with the answers given there, it's generally considered better to "bump" the old one, perhaps by editing it to ask for further clarification, rather than create a new question.
EDIT: As requested, some very brief sample code follows. This is probably not the best code around, and I haven't tested it, so it may be a little iffy. Just for clarification, the THRESHOLD allows the user to move their finger a little while tapping (up to 3px), because it's very difficult to tap without moving your finger a little.
MyView.h
#define THRESHOLD 3*3
#interface MyView : UIView
{
CGPoint touchPoint;
CGPoint drawPoint;
UIImage theImage;
}
#end
MyView.m
#implementation MyView
- (id) initWithFrame:(CGRect) newFrame
{
if (self = [super initWithFrame:newFrame])
{
touchPoint = CGPointZero;
drawPoint = CGPointMake(-1, -1);
theImage = [[UIImage imageNamed:#"myImage.png"] retain];
}
return self;
}
- (void) dealloc
{
[theImage release];
[super dealloc];
}
- (void) drawRect:(CGRect) rect
{
if (drawPoint.x > -1 && drawPoint.y > -1)
[theImage drawAtPoint:drawPoint];
}
- (void) touchesBegan:(NSSet*) touches withEvent:(UIEvent*) event
{
touchPoint = [[touches anyObject] locationInView:self];
}
- (void) touchesEnded:(NSSet*) touches withEvent:(UIEvent*) event
{
CGPoint point = [[touches anyObject] locationInView:self];
CGFloat dx = point.x - touchPoint.x, dy = point.y - touchPoint.y;
if (dx + dy < THRESHOLD)
{
drawPoint = point;
[self setNeedsDisplay];
}
}
#end