if([labelView.layer containsPoint:touchPoint]) not working in Xcode - iphone

Can anyone tell that, i have taken draggable label with UIPangesture when dragging and releasing mouse i am finding touch point using
CGPoint touchPoint = [panGesture locationInView:self.view];
now i want to check on which label is this label dragged.For this i am using this code
for(UILabel *labelView in self.view.subviews){
if ([labelView isMemberOfClass:[UILabel class]]) {
NSLog(#"%#",NSStringFromCGPoint(touchPoint ));
NSLog(#"%#",NSStringFromCGRect(labelView.layer.frame));
if([labelView.layer containsPoint:touchPoint]){
int i=[[labelView.subviews objectAtIndex:0] tag];
NSLog(#">>>> %d",i);
}
}
}

panGesture passed to the gesture handler method has property 'view' that points which UILabel object you've setup with the recognizer
EDIT:
*-- the answe above was wrong. Thanks Jacky for pointing me out --*
self.view's hitTest:withEvent: method would return the view at the point. Pass nil to withEvent:
if self.view has subviews other than UILabel too and you want to avoid one of those returned, call
bool CGRectContainsPoint (
CGRect rect,
CGPoint point
);
for each label. Pass frame for rect, touchpoint for point
for(UILabel *labelView in self.view.subviews){
if ([labelView isMemberOfClass:[UILabel class]]) {
if(CGRectContainsPoint(labelView.frame,touchPoint)){
int i=[[labelView.subviews objectAtIndex:0] tag];
NSLog(#">>>> %d",i);
}
}
}
EDIT:
The reason why .layer's containsPoint: didn't work:
thePoint A point in the receiver’s coordinate system.
In your code, touchPoint is in self.view's coordinate system that is different from any label's coordinate system

Thanks for replying.
This worked for me
if ([labelView.layer containsPoint:[labelView.layer convertPoint:touchPoint fromLayer:labelView.layer.superlayer]] == TRUE)
but your answer is also correct i have check that.

Related

frame by frame animation with UIGestureRecognizer

I would like to show an animation with images of an object rotating.
I have an NSArray with frames of the object and I would like to display them frame by frame with the property of UIImageView animationImages.
The problem is that I would like to control the animation with UISwipeGestureRecognizer (Right and Left). And depending on the speed of the gesture the object should rotate faster or slower. I think is not possible because the gesture it is called just once and not continuously.
(NOTE: this is my first question in StackOverflow)
Thank you in advance
EDIT: I just post my solution. Maybe it can be useful for anybody. I think it's useful.
Firstly: add gesture to the view.
self.recognizer = [[UISwipeGestureRecognizer alloc] init];
self.recognizer.cancelsTouchesInView=NO;
[self.view addGestureRecognizer:self.recognizer];
Secondly: in tocuhMoved method I display the frame that I need depending of the direction of the previous touch. It is called by the event of the user.
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
NSInteger image= [self.animationView.animationImages indexOfObject:self.animationView.image];
UITouch *touch = [touches anyObject];
NSLog(#"Touch moved with index:%i", image);
if ((positionTouch.x<[touch locationInView:self.animationView].x)) {
if (image==24) {
self.animationView.image=[self.animationView.animationImages objectAtIndex:0];
}
else{
self.animationView.image=[self.animationView.animationImages objectAtIndex:image+1];
}
}
else if((positionTouch.x>[touch locationInView:self.animationView].x)){
if (image==0) {
self.animationView.image=[self.animationView.animationImages objectAtIndex:24];
}
else{
self.animationView.image=[self.animationView.animationImages objectAtIndex:image-1];
}
}
positionTouch= [touch locationInView:self.animationView];
}
Don't forget <UIGestureRecognizerDelegate>
with this method, I fill the array of frames...
-(void)addPictures{
NSMutableArray* mArray=[[NSMutableArray alloc]initWithCapacity:25];
for (int i=0; i<25; i++) {
[mArray insertObject:[UIImage imageNamed:[NSString stringWithFormat:#"Picture %i.jpg", i+1]] atIndex:i];
}
self.animationView.image=[mArray objectAtIndex:0];
self.animationView.animationImages=mArray;
[self.view addSubview:self.animationView];
}
It's actually very simple to control the speed of an animation. In fact, it's so simple (because CALayer conforms to the CAMediaTiming protocol) that the property to control it is literally called speed. It's all a matter of using the gesture as a sort of analog for a slider, and calculating an x value relative to it's location onscreen. This should be a suitable starting point:
//Speed changes necessitate a change in time offset, begin time, and
//speed itself. Simply assigning to speed it not enough, as the layer needs
//to be informed that it's animation timing function is being mutated. By
//assigning a new time offset and a new begin time, the layer
//automatically adjusts the time of any animations being run against it
layer.timeOffset = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
layer.beginTime = CACurrentMediaTime();
layer.speed = ([self.gesture locationInView:self.view].x / CGRectGetWidth(self.view.bounds));

How to test if a point is in a view

I have a UIImageView and I have a CGPoint on the screen. I want to be able to test that point to see if it is in the UIImageView. What would be the best way to do this?
CGPoint is no good with a reference point. If your point is in window's coordinates then you can get it using
CGPoint locationInView = [imageView convertPoint:point fromView:imageView.window];
if ( CGRectContainsPoint(imageView.bounds, locationInView) ) {
// Point lies inside the bounds.
}
You may also call pointInside:withEvent: method
if ( [imageView pointInside:locationInView withEvent:nil] ) {
// Point lies inside the bounds
}
Tested in Swift 4
view.frame.contains(point)
if(CGRectContainsPoint([myView frame], point))
where point is your CGPoint and myView is your UIImageView
I'll assume you have a full-screen window (pretty reasonable, I think). Then you can transform the point from the window's coordinate space to the UIImageView's using:
CGPoint point = ...
UIWindow window = ...
UIImageView imageView = ...
CGPoint transformedPoint = [window convertPoint:point toView:imageView];
Then, you can test if the point is in the image view's frame as follows:
if(CGRectContainsPoint(imageView.frame, transformedPoint))
{
// do something interesting....
}
In Swift 3
let isPointInFrame = UIScreen.main.bounds.contains(newLocation)

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 images appear... How?

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

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