CALayer with UIImageView - ios

I have below code:
IBOutlet UIImageView *img_Logo;
...
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
CALayer *ca_Logo = img_Logo.layer;
ca_Logo.position = CGPointMake(400, 400);
ca_Logo.duration = 2.0f;
[ca_Logo setNeedsDisplay];
}
When a touch event is triggered, the logo will disappear, but when I remove ca_Logo.duration = 2.0f, that ca_Logo will move, but it was not an animation, just instantly disappear and appear to a new location.
Is there anything wrong with it? img_Logo is an UIImageView with IBOutlet or I need to program it without Interface builder?
I want to move the image from CGPointMake(400, 400) to CGPointMake(200, 400)

I think you need to program it without using the interface builder try this code
UIImage *image = [UIImage imageNamed:#"img_Logo.png"];
CALayer *img = [CALayer layer];
img.contents = (id)image.CGImage;
img.bounds = CGRectMake(0, 0, 100, 200);
img.position = CGPointMake(400, 400);
[self.view.layer addSublayer:img];

if you just want to animate from one frame to another, try below:
[UIView animateWithDuration:1.0 animations:^{
[self.img_Logo setFrame:CGRectMake(200, 400, youImageViewWidth, youImageViewHeight)];
}];
I don't get your point using touchesBegan and touchesMoved

Related

Rotate UIButton on change of orientation

I have round button which consists of the following image
Now on rotation of device I want to rotate the button in a way that the image maintains the orientation.
How can I achieve this,
I do not want to change the frame of the button i want it to stay where it is I just want to transform the button.
If you have an IBOutlet Object.
theButton.transform = CGAffineTransformMakeRotation(M_PI / -4);
If you want to create run time button on view.
- (void)viewDidLoad {
[super viewDidLoad];
UIButton *btn=[UIButton buttonWithType:UIButtonTypeRoundedRect];
[btn setFrame:CGRectMake(100, 100, 200, 44)];
btn.transform=CGAffineTransformMakeRotation(M_PI / -4);
[btn setTitle:#"RakeshBhatt" forState:UIControlStateNormal];
[self.view addSubview:btn];
}
To rotate a image view try this
// Set the anchor point and center so the view swings from the upper right
imageView.layer.anchorPoint = CGPointMake(1.0, 0.0);
imageView.center = CGPointMake(CGRectGetWidth(self.view.bounds), 0.0);
// Rotate 90 degrees to hide it off screen
CGAffineTransform rotationTransform = CGAffineTransformIdentity;
rotationTransform = CGAffineTransformRotate(rotationTransform, DegreesToRadians(90));
swingView.transform = rotationTransform;

It is possible to animate UIImage Thumb of the UISlider?

I would like to to animate (blink) thumb of the UISlider when user first enter the app (to indicate what to click).
I set UIImage as a thumb :
[self.textNavigationSlider setThumbImage:thumbImage forState:UIControlStateNormal];
Can I somehow animate it (maybe just change alpha of this UIImage as animation) ?
PS (This play button is the UIImage)
I don't believe you can animate the alpha value of an image, and we don't have access to an the thumb's image view (if it has one) to animate its alpha. One thing you can do is add an image view as a subview of the slider, and make it slightly bigger than the thumb image, and animate its alpha value (it will be behind the thumb's image, so it will show up as a pulsating ring). In this example, I set the image view's frame in thumbRectForBounds:trackRect:value:, and cancel the animation in touchesBegan,
#interface RDSlider ()
#property (strong, nonatomic) UIImageView *iv;
#end
#implementation RDSlider // subclass of UISlider
-(void)awakeFromNib {
self.minimumTrackTintColor = [UIColor colorWithRed:75/255.0 green:180/255.0 blue:150/255.0 alpha:1];
self.maximumTrackTintColor = [UIColor colorWithRed:50/255.0 green:120/255.0 blue:100/255.0 alpha:1];
[self setThumbImage:[self createThumbImage] forState:UIControlStateNormal];
self.iv = [UIImageView new];
self.iv.backgroundColor = [UIColor greenColor];
[self addSubview:self.iv];
}
-(void)didMoveToWindow {
[UIView animateWithDuration:.6 delay:0 options:UIViewAnimationOptionAutoreverse|UIViewAnimationOptionTransitionCrossDissolve|UIViewAnimationOptionRepeat|UIViewAnimationOptionCurveEaseInOut animations:^{
self.iv.alpha = 0;
} completion:^(BOOL finished) {
[self.iv removeFromSuperview];
self.iv = nil;
}];
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[self.iv.layer removeAllAnimations]; // calling this causes the animation's completion block to be executed
[super touchesBegan:touches withEvent:event];
}
- (CGRect)thumbRectForBounds:(CGRect)bounds trackRect:(CGRect)rect value:(float)value {
CGRect thumbRect = [super thumbRectForBounds:bounds trackRect:rect value:value];
self.iv.frame = CGRectInset(thumbRect,-2,-2);
self.iv.layer.cornerRadius = self.iv.frame.size.width/2.0;
self.iv.layer.masksToBounds = YES;
return thumbRect;
}
-(UIImage *) createThumbImage {
UIBezierPath *border = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, 28, 28)];
UIBezierPath *center = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(.5, .5, 27, 27)];
UIGraphicsBeginImageContextWithOptions(CGSizeMake(border.bounds.size.width, border.bounds.size.height), NO, 0.0);
[self.minimumTrackTintColor setFill];
[border fill];
[[UIColor whiteColor] setFill];
[center fill];
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}
If you want it for one time follow below steps.
Create new UIImageView let's say fakeImageView.
Animate it using UIViewAnimation
Once animation is done, hide it... (fakeImageView.hidden = YES)
For UIViewAnimation tutorial, visit here or here
You could make an exact copy of the slider, except for no thumb image, and put it underneath the first one. Then animate the alpha of the whole first slider, which should give the impression of only animating the thumb, in theory ;-) When animation is completed, you can delete the second slider.
You can access the UISlider object.subviews. Usually (not guaranteed) the third element (which should be the .lastObject) is the UIImageView for the thumb image.

Circle masked view animating too fast, and not tappable

I'm trying to make a circle-masked image view with animated mask, and played with different solutions. The example below does the job but I've got two problems with it:
1) Why is it that I cannot make the image tappable? Adding eg. a UITapGestureRecognizer does not work. My guess is that the mask prevents the touch actions being propagated to the lower level in the view hierarchy.
2) Animating the mask is running very fast and I cannot adjust the duration using UIView block animation
How can I solve these?
- (void) addCircle {
// this is the encapsulating view
//
base = [[UIView alloc] init];
//
// this is the button background
//
base_bgr = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"c1_bgr.png"]];
base_bgr.center = CGPointMake(60, 140);
[base addSubview:base_bgr];
//
// icon image
//
base_icon = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"c1_ico.png"]];
base_icon.center = CGPointMake(186*0.3/2, 182*0.3/2);
base_icon.transform = CGAffineTransformMakeScale(0.3, 0.3);
[base addSubview:base_icon];
//
// the drawn circle mask layer
//
circleLayer = [CAShapeLayer layer];
// Give the layer the same bounds as your image view
[circleLayer setBounds:CGRectMake(0.0f, 0.0f, [base_icon frame].size.width,
[base_icon frame].size.height)];
// Position the circle
[circleLayer setPosition:CGPointMake(186*0.3/2-7, 182*0.3/2-10)];
// Create a circle path.
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:
CGRectMake(0.0f, 0.0f, 70.0f, 70.0f)];
// Set the path on the layer
[circleLayer setPath:[path CGPath]];
[[base layer] setMask:circleLayer];
[self.view addSubview:base];
base.center = CGPointMake(100, 100);
base.userInteractionEnabled = YES;
base_bgr.userInteractionEnabled = YES;
base_icon.userInteractionEnabled = YES;
//
// NOT working: UITapGestureRecognizer
//
UITapGestureRecognizer *tapgesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapit:)];
[base_icon addGestureRecognizer:tapgesture];
//
// BAD but WORKS :) properly positioned UIButton over the masked image
//
base_btn = [UIButton buttonWithType:UIButtonTypeCustom];
base_btn.frame = CGRectMake(base.frame.origin.x, base.frame.origin.y, base_icon.frame.size.width, base_icon.frame.size.height);
[base_btn addTarget:self action:#selector(tapit:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:base_btn];
}
This is the tap handler, and here's the mask animation. Whatever number I tried in duration, it is animating fast - approximately 0.25 second, and I cannot adjust it.
- (void) tapit:(id) sender {
//...
[UIView animateWithDuration:1.0
delay:0.0
options:UIViewAnimationOptionCurveEaseOut
animations:^ {
[circleLayer setTransform:CATransform3DMakeScale(10.0, 10.0, 1.0)];
}
completion:^(BOOL finished) {
// it is not necessary if I manage to make the icon image tappable
base_btn.frame = [base convertRect:base_icon.frame toView:self.view];
}];
}
}
1) touches are not propagated down from base because it's initiated without a frame, so its frame will be CGRectZero. Views don't get touch events that start outside of their bounds. Simply set a valid frame on base that includes entire tap target.
2) setTransform: on a layer invokes an implicit animation which uses Core Animation's default duration of 0.25 (you guessed it right :)). The best solution would be to use CABasicAnimation instead of UIView-based animation. Something like this:
CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:#"transform.scale"];
scaleAnimation.toValue = #(10.0f);
scaleAnimation.duration = 2;
[circleLayer addAnimation:scaleAnimation forKey:nil];
Note: by default, CABasicAnimation will remove itself from a layer when complete and the layer will snap back to old values. You can prevent it by for example setting that animation's removedOnCompletion property to NO and removing it yourself later using CALayer's removeAnimationForKey: method (just set a key instead of passing nil wheen adding the animation), but that depends on what exactly you want to accomplish with this.

Center of second animation not using new position

I am having an issue with running two animations in iOS. First i am trying to move the image from the bottom of the screen to the top by changing frame in the first animation set, then on completion i am trying to extend the length of the object by transforming the scale. But for some reason once the first animation is finished the object goes back to the original place at the bottom of the screen and the growing transformation happens off the screen. Can anyone help me with this? Thanks in advance for your help, here is my code:
CGRect fullview = CGRectMake(59, 102, 650, 150);
CGRect iconView = CGRectMake(59, 102, 290, 150);
CGRect textView = CGRectMake(349, 102, 360, 150);
[_profileBtn setEnabled:FALSE];
[_profileBtn setHidden:TRUE];
[UIView animateWithDuration:1 animations:^{ // animate the following:
_profileIcon.frame = iconView; // move to new location
_profileText.frame = textView; // move to new location
_profileBackground.frame =fullview;
}completion:^(BOOL finished){
[UIView animateWithDuration:1 animations:^{ // animate the following:
_profileBackground.transform = CGAffineTransformMakeScale(1, 5.64);
}];
}];
Check out the documentation for the UIView transform property. Specifically, what happens to the object's frame if you adjust the transform. I think instead of performing the second animation on the UIView's transform, you should apply it to the scale of its layer's transform.
I figure out a solution that was close to what i wanted. This will do the translation and the movement at the same time:
CGRect iconView = CGRectMake(59, 102, 290, 150);
CGRect textView = CGRectMake(349, 102, 360, 150);
_profileIcon.frame = iconView; // move to new location
_profileText.frame = textView; // move to new location
CGAffineTransform scale = CGAffineTransformMakeScale(1, 5.00);
CGRect fullview = CGRectMake(59, 40, 650, 150);
_profileBackground.frame = CGRectApplyAffineTransform(fullview,scale);

zoom in UIImageView and UIImageView.center

Trying to zoom in / out an imageView.
i've managed that successfully so now i'm trying to place some buttons on the view and when button tapped to zoom on that area.
How can i implement that?
here is my code so far
-(void)zoomHere:(UIButton *)sender{
NSLog(#"zoom in");
//[self performSelector:#selector()
// withObject:nil
// afterDelay:1.6f];
CGAffineTransform transformer = CGAffineTransformScale(imageView.transform, 1.05, 1.05);
if (transformer.a < 5) {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration: 0.2];
imageView.transform = transformer;
[UIView setAnimationDelegate:self];
[UIView commitAnimations];
}
}
and the view did load
- (void)viewDidLoad
{
[super viewDidLoad];
UIView *buttonView = [[UIView alloc]initWithFrame:CGRectMake(00.0, 20.0, 768, 1004.0)];
zoomHere = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[zoomHere addTarget:self
action:#selector(zoomHere:)
forControlEvents:UIControlEventTouchDown];
[zoomHere setTitle:#"ZoomIN" forState:UIControlStateNormal];
zoomHere.frame = CGRectMake(80.0, 210.0, 160.0, 40.0);
[buttonView addSubview:zoomHere];
buttonView.multipleTouchEnabled = YES;
[self.view addSubview:buttonView];
}
It still zoom in but not on that area where the button sits on screen!
if you want to use scale transform, you probably should use translate transform as welllike this:
CGAffineTransform scale = CGAffineTransformMakeScale(1.05, 1.05);
CGAffineTransform translate = CGAffineTransformMakeTranslation(10, 20);
CGAffineTransform delta = CGAffineTransformConcat(scale, translate);
imageView.transform = CGAffineTransformConcat(imageView.transform, delta);
this is how you know the position of button on your image view:
[imageView convertPoint:button.center fromView:self.view]
so if you know button's coordinates and your current scale then you can calculate new translate transformBut as for me, i would rather use scroll view to zoom in and zoom out that image view. You can have nice bouncing animations and zooming animations, also you can have pan and pinch, but of cource it is up to you.

Resources