Not Getting Proper location of CALayer iOS - iphone

I am working CALayer in iOS added a sublayers in myView and trying to get touch event through touches began but i am getting touch event not at the location where i have drawn the layer, plz help me in correcting it if smthing is wrong.
UIView *myView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
myView.backgroundColor = [UIColor whiteColor];
magicButton_ = [UIButton buttonWithType:UIButtonTypeRoundedRect];
magicButton_.frame = CGRectMake(10., 10., 300., 44.);
[magicButton_ setTitle:#"Invoke Magic!" forState:UIControlStateNormal];
[magicButton_ addTarget:self action:#selector(toggleMoney:) forControlEvents:UIControlEventTouchUpInside];
[myView addSubview:magicButton_];
simpleLayer_ = [[CALayer alloc]init];
simpleLayer_.bounds = CGRectMake(0., 0., 150., 20.);
simpleLayer_.position = CGPointMake((myView.center.x),(myView.center.y));
simpleLayer_.name = #"redlayer";
simpleLayer_.delegate = self;
simpleLayer_.backgroundColor = [[UIColor redColor]CGColor];
[myView.layer addSublayer:simpleLayer_];
self.view = myView;
-(void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
CGPoint location = [[touches anyObject] locationInView:self.view];
CALayer *hitLayer = [self.view.layer hitTest:[self.view convertPoint:location fromView:nil]];
NSLog(#"Location %f %f",location.x,location.y);
[self displayInfo:hitLayer.name];
}
-(void)displayInfo:(NSString *)nameOfLayer
{
NSLog(#"%#",nameOfLayer);
}
2013-10-14 13:13:37.374 MyLayerProj[1750:11303] (null)
2013-10-14 13:13:38.468 MyLayerProj[1750:11303] Location 87.000000 269.000000
2013-10-14 13:13:38.469 MyLayerProj[1750:11303] (null)
2013-10-14 13:13:39.239 MyLayerProj[1750:11303] Location 112.000000 278.000000
2013-10-14 13:13:39.240 MyLayerProj[1750:11303] redlayer
2013-10-14 13:13:40.479 MyLayerProj[1750:11303] Location 119.000000 278.000000
I have also included the logs which i am getting while running the code.

The [self.view convertPoint:location fromView:nil] in your call to -[CALayer hitTest] means "convert location from the co-ordinate space of the window to the co-ordinate space of self.view".
However, location is already in the co-ordinate space of the view, because you obtained it from passing self.view to -[UITouch locationInView:].

Related

Touch position highlight

I'm trying to highlight a touch event by using UIGestureRecognizer, so far I can get the CGPoint where the user touched but I don't know how to highlight that specific area since I don't know much about animation.
The code so far on viewDidLoad:
UITapGestureRecognizer *singleFingerTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(gradientTouchDown:)];
[self addGestureRecognizer:singleFingerTap];
The method that gets the position of the touch:
-(void)gradientTouchDown:(UIGestureRecognizer*)recognizer{
NSLog(#"tap detected.");
CGPoint point = [recognizer locationInView:nil];
NSLog(#"x = %f y = %f", point.x, point.y );
}
By doing some study I think I need to add the code above with a View animation, but how can I recognize the touch? the code:
[UIView animateWithDuration:0.3f
delay:0.0
options:UIViewAnimationOptionCurveEaseIn
animations:^
{
[sender setAlpha:0.3f];
}
completion:^(BOOL finished)
{
[sender setAlpha:1.0f];
}];
I really need help on this one, any question just ask, I'm always around here :)
This is how I implemented my animation in one of my projects for a button. The animation just puts a glow around the button when pressed (just like the glow you see when you press an year button on the graph view of built in stocks app)
First, add these targets to the button:
[button addTarget:self action:#selector(myButtonPressed:) forControlEvents:UIControlEventTouchDown];
[button addTarget:self action:#selector(myButtonReleased:) forControlEvents:UIControlEventTouchUpInside];
Then these methods looks like this:
- (void) myButtonPressed:(id) sender
{
UIButton *button = (UIButton *) sender;
CABasicAnimation *shadowRadius = [CABasicAnimation animationWithKeyPath:#"shadowRadius" ];
shadowRadius.delegate = self;
[shadowRadius setFromValue:[NSNumber numberWithFloat:3.0]];
[shadowRadius setToValue:[NSNumber numberWithFloat:15.0]];
[shadowRadius setDuration:0.2f];
[[button layer] addAnimation:shadowRadius forKey:#"shadowRadius"];
button.layer.shadowRadius = 15.0f;
}
- (void) myButtonReleased:(id) sender
{
UIButton *button = (UIButton *) sender;
CABasicAnimation *shadowRadius = [CABasicAnimation animationWithKeyPath:#"shadowRadius" ];
shadowRadius.delegate = self;
[shadowRadius setFromValue:[NSNumber numberWithFloat:15.0]];
[shadowRadius setToValue:[NSNumber numberWithFloat:3.0]];
[shadowRadius setDuration:0.2f];
//shadowRadius.autoreverses = YES;
[[button layer] addAnimation:shadowRadius forKey:#"shadowRadius"];
button.layer.shadowRadius = 3.0f;
button.selected = YES;
}
Hi and thanks for the help, I came out with a custom solution for a similar glow effect related to the Apple "Shows Touch on Highlight" here is the code for the glow:
-(void)gradientTouchDown:(UIGestureRecognizer*)recognizer{
NSLog(#"tap detected");
CGPoint point = [recognizer locationInView:nil];
NSLog(#"x = %f y = %f", point.x, point.y );
UIImage* image;
UIColor *color = [UIColor whiteColor];
UIGraphicsBeginImageContextWithOptions(recognizer.view.bounds.size, NO, [UIScreen mainScreen].scale); {
[recognizer.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIBezierPath* path = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, recognizer.view.bounds.size.width, recognizer.view.bounds.size.height)];
[color setFill];
[path fillWithBlendMode:kCGBlendModeSourceAtop alpha:1.0];
image = UIGraphicsGetImageFromCurrentImageContext();
} UIGraphicsEndImageContext();
UIView* glowView = [[UIImageView alloc] initWithImage:image];
glowView.center = self.center;
[self.superview insertSubview:glowView aboveSubview:self];
glowView.alpha = 0;
glowView.layer.shadowColor = color.CGColor;
glowView.layer.shadowOffset = CGSizeZero;
glowView.layer.shadowRadius = 10;
glowView.layer.shadowOpacity = 1.0;
CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:#"opacity"];
animation.fromValue = #(0.0f);
animation.toValue = #(0.6f);
//animation.repeatCount = 2 ? HUGE_VAL : 0;
animation.duration = 0.2;
animation.autoreverses = YES;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[glowView.layer addAnimation:animation forKey:#"pulse"];
}
Any suggestion for improvement is welcome, so far it works for me :)

add uiview as subview to MKmapview using MKMapPoint

Is it possible to add uiview in MKMapPoint,The code i have tried is given below but it's doesn't work. Any help is appreciated.
-(IBAction)foundTap:(UITapGestureRecognizer *)recognizer
{
CGPoint point = [recognizer locationInView:self.myMapView];
CLLocationCoordinate2D tapPoint = [self.myMapView convertPoint:point toCoordinateFromView:self.view];
MKMapPoint myMapPoint = MKMapPointForCoordinate(tapPoint);
UIView *mymapview=[[UIView alloc]initWithFrame:CGRectMake(myMapPoint.x, myMapPoint.y, 20, 20)];
mymapview.backgroundColor=[UIColor greenColor];
[self.view addSubview:mymapview];
}
Thanks.
[yourmapview addSubview: mymapview];
Add your mymapview on the map view like the above.

Double tap zoom crash and display unrecognized sector in iOS

I want to implement double tap zoom in and zoom out. so in my project i have not used any xib or storyboard its pure programming view (hard-coaded).
I dont have scrollview in my project so i added scroll view and add my image-view as subview into scoll-view.
Than i Used "UIGestureRecognizer" and "touch began" but when i press double click my app get crash. I don't recognized problem as i am new to IOS Please suggest some solution
Here is my Code
ScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0.0, 0.0, 1024,768)];
UIView *mixContainerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1024, 768)];
mixContainerView.backgroundColor = [UIColor clearColor];
[mixContainerView addSubview:ScrollView];
backgroundImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 1024, 768)];
backgroundImageView.image = [UIImage imageNamed:[NSString stringWithFormat:#"app%03d_location%02d_background", location.application.id.intValue, location.id.intValue]];
[ScrollView addSubview:backgroundImageView];
- (void)tapTwice:(UIGestureRecognizer *)gestureRecognizer{
//on a double tap, call zoomToRect in UIScrollView
float newScale = [ScrollView zoomScale] * 1.5;
if (newScale > self.ScrollView.maximumZoomScale){
newScale = self.ScrollView.minimumZoomScale;
CGRect zoomRect = [self zoomRectForScale:newScale withCenter:[gestureRecognizer locationInView:gestureRecognizer.view]];
[ScrollView zoomToRect:zoomRect animated:YES];}
else{
newScale = self.ScrollView.maximumZoomScale;
CGRect zoomRect = [self zoomRectForScale:newScale withCenter:[gestureRecognizer locationInView:gestureRecognizer.view]];
[ScrollView zoomToRect:zoomRect animated:YES];}}
// Touch began for touch event to display and hide controll buttons
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
if(((UITouch *)[touches anyObject]).tapCount == 2)
{
UITapGestureRecognizer *tapTwice = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapTwice)];
tapTwice.numberOfTapsRequired = 2;
//stops tapOnce from overriding tapTwice
//then need to add the gesture recogniser to a view - this will be the view that recognises the gesture
[self.view addGestureRecognizer:tapTwice];
else{
if(screenTimer)
{
[screenTimer invalidate];
screenTimer = nil;
}
mode1View.hidden=NO;
screenTimer = [NSTimer scheduledTimerWithTimeInterval:3.0 target:self selector:#selector(turnOffScreen) userInfo:nil repeats:NO];}}
- (void)turnOffScreen{
NSLog(#"TURN OFF SCREEN");
if(screenTimer!=nil)
{
mode1View.hidden=YES;
}}
- (CGRect)zoomRectForScale:(float)scale withCenter:(CGPoint)center {
CGRect zoomRect;
// the zoom rect is in the content view's coordinates.
// At a zoom scale of 1.0, it would be the size of the imageScrollView's bounds.
// As the zoom scale decreases, so more content is visible, the size of the rect grows.
zoomRect.size.height = [ScrollView frame].size.height / scale;
zoomRect.size.width = [ScrollView frame].size.width / scale;
// choose an origin so as to get the right center.
zoomRect.origin.x = center.x - (zoomRect.size.width / 2.0);
zoomRect.origin.y = center.y - (zoomRect.size.height / 2.0);
return zoomRect;
}
Error
unrecognized selector sent to instance 0x7b2f540
2013-03-13 18:46:09.960 VSL[9352:c07] *** Terminating app due to uncaught exception ' NSInvalidArgumentException', reason: '-[ViewController tapTwice]: unrecognized selector sent to instance 0x7b2f540'
*** First throw call stack:
(0x1f38012 0x1854e7e 0x1fc34bd 0x1f27bbc 0x1f2794e 0x75385a 0x75299b 0x7540df 0x756d2d 0x756cac 0x74ea28 0x4bb972 0x4bbe53 0x499d4a 0x48b698 0x1e93df9 0x1e93ad0 0x1eadbf5 0x1ead962 0x1edebb6 0x1eddf44 0x1edde1b 0x1e927e3 0x1e92668 0x488ffc 0x1fbd 0x1ee5 0x1)
libc++abi.dylib: terminate called throwing an exception
You need to change:
UITapGestureRecognizer *tapTwice = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapTwice)];
To:
UITapGestureRecognizer *tapTwice = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapTwice:)];
The method tapTwice: takes a paramater.

Accessing the current position of UIView during animation

I am trying to find the current position of an iPhone ImageView that is animating across the screen.
I create and animate the imageView like so
-(IBAction)button:(UIButton *)sender{
UIImageView *myImageView =[[UIImageView alloc] initWithImage:
[UIImage imageNamed:#"ball.png"]];
myImageView.frame = CGRectMake(0, self.view.frame.size.height/2, 40, 40);
[self.view addSubview:myImageView];
[myArray addObject:myImageView];
[UIView animateWithDuration:.5
delay:0
options:(UIViewAnimationOptionAllowUserInteraction) // | something here?)
animations:^{
myImageView.frame = CGRectOffset(myImageView.frame, 500, 0);
}
completion:^(BOOL finished){
[myArray removeObject:myImageView];
[myImageView removeFromSuperview];
[myImageView release];
}
];
}
then to detect the current CGPoint of the imageView I call this method every 60th of a second
-(void)findPoint{
for (UIImageView *projectile in bullets) {
label.text = [NSString stringWithFormat:#"%f", projectile.center.x];
label2.text = [NSString stringWithFormat:#"%f", projectile.center.y];
}
}
However this only gives me the point where the animation ends, I want to get the current CGPoint of the image that is animating across the screen. Is there an option that I need to apply other than UIViewAnimationOptionAllowUserInteraction to do this? If not, how do I get the current position of an animating imageView?
You can use the presentationLayer - a property of the CALayer that "provides a close approximation to the version of the layer that is currently being displayed". Just use it like this:
CGRect projectileFrame = [[projectile.layer presentationLayer] frame];
Swift 5:
Get temporary position and size (CGRect) during the animation with:
let currentFrame = projectileFrame.layer.presentation()!.frame

Pinch to take photo full screen like Reeder apps

Trying to come up with a method for doing the exact same thing the reeder apps creator does in his iphone/ipad apps with pinch-to-expand photos to full screen.
I have a uiimageview in a table cell that I want to transition to a full screen view on pinch open, or maybe double tap. Would like to use a similar animation as well.
Any tips would be appreciated!
Ok I managed to put this together myself. Not really sure how to use a transition method, but I needed to duplicate the view in the same location and then blow it up.
http://screencast.com/t/MLTuGkIYh
So in my cell that contains the big image I hook up both the pinch and tap gesture recognizers.
self.imageView.contentMode = UIViewContentModeScaleAspectFit;
self.imageView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
UIPinchGestureRecognizer *pinchGesture = [[[UIPinchGestureRecognizer alloc] initWithTarget:self action:#selector(handlePinchGesture:)] autorelease];
UITapGestureRecognizer *tapGesture = [[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap:)] autorelease];
tapGesture.numberOfTapsRequired = 2;
self.imageView.userInteractionEnabled = YES;
self.imageView.multipleTouchEnabled = YES;
[self.imageView addGestureRecognizer:pinchGesture];
[self.imageView addGestureRecognizer:tapGesture];
[cell.contentView addSubview:self.imageView];
and then here's the rest of the code. Basically when I recognized the gesture (and for pinching, make sure its finished) I place the duplicate view in the same exact location (gained via the convertRect stuff), and then animate its frame and background color. When returning from it, I do the inverse.
- (void)handlePinchGesture:(id)sender
{
if (((UIPinchGestureRecognizer *)sender).state == UIGestureRecognizerStateEnded) {
if(((UIPinchGestureRecognizer *)sender).view == self.imageView)
{
if (((UIPinchGestureRecognizer *)sender).scale > 1) {
[self showFloorPlanFullScreen];
}
} else {
if (((UIPinchGestureRecognizer *)sender).scale < 1) {
[self closeFloorPlanFullScreen];
}
}
}
}
- (void)handleTap:(id)sender
{
if (((UITapGestureRecognizer *)sender).view == self.imageView) {
[self showFloorPlanFullScreen];
} else {
[self closeFloorPlanFullScreen];
}
}
- (void)showFloorPlanFullScreen
{
CGRect newRect = [self.imageView convertRect:self.imageView.bounds toView:[self.splitViewController.view superview]];
UIImage *image = self.imageView.image;
self.fullScreenImageView = [[[UIImageView alloc] initWithImage:image] autorelease];
UIPinchGestureRecognizer *pinchGesture = [[[UIPinchGestureRecognizer alloc] initWithTarget:self action:#selector(handlePinchGesture:)] autorelease];
UITapGestureRecognizer *tapGesture = [[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap:)] autorelease];
tapGesture.numberOfTapsRequired = 2;
self.fullScreenImageView.userInteractionEnabled = YES;
self.fullScreenImageView.multipleTouchEnabled = YES;
[self.fullScreenImageView addGestureRecognizer:pinchGesture];
[self.fullScreenImageView addGestureRecognizer:tapGesture];
self.fullScreenImageView.contentMode = UIViewContentModeScaleAspectFit;
self.fullScreenImageView.frame = newRect;
self.fullScreenImageView.backgroundColor = [UIColor clearColor];
[[self.splitViewController.view superview] addSubview:self.fullScreenImageView];
CGRect splitViewRect = self.splitViewController.view.frame;
[UIView animateWithDuration:0.5 animations:^{
self.fullScreenImageView.backgroundColor = [UIColor blackColor];
self.fullScreenImageView.frame = splitViewRect;
}];
}
- (void)closeFloorPlanFullScreen
{
CGRect newRect = [self.imageView convertRect:self.imageView.bounds toView:[self.splitViewController.view superview]];
[UIView animateWithDuration:0.5
animations:^{
self.fullScreenImageView.backgroundColor = [UIColor clearColor];
self.fullScreenImageView.frame = newRect;
}
completion:^(BOOL finished) {
[self.fullScreenImageView removeFromSuperview];
self.fullScreenImageView = nil;
}];
}
If you want the picture to actual resize while zooming, I would recommend adding the duplicate view as soon as the pinching starts (and as long as its scaling > 1) and then apply the transformation:
CGAffineTransform myTransformation = CGAffineTransformMakeScale(((UIPinchGestureRecognizer *)sender).scale, ((UIPinchGestureRecognizer *)sender).scale);
self.fullScreenImageView.transform = myTransformation;
As soon as the pinching hits a end state, I would then fade in the black and adjust the frame. I decided not to go with this method as I think just recognizing the pinch out or double tap is good enough.
You have to embed your UIImageView in an UIControl and link an IBAction to UIControl events.
Use a UIPinchGestureRecognizer on the image view to recognize the pinch and the UIView transition methods to blow the image view up to full size.