CGAffineTransformScale a UIButton - iphone

i am trying to scale in and out a UIButton in the main view, when i press a action button at first, the button zooms in and when i press it again it zooms out but when i press it again to zoom in.. nothing happens.. here is my code:
THE METHODS TO ZOOM IN AND ZOOM OUT ARE IN A OBJECTIVE-C CATEGORY ON UIVIEW
- (void)viewDidLoad
[super viewDidLoad];
//this button is being added in the storyboard
[self.viewToZoom removeFromSuperview];
}
- (IBAction)zoomButton:(id)sender {
if (isShown) {
[self.view removeSubviewWithZoomOutAnimation:self.viewToZoom duration:1.0 option:0];
isShown = NO;
} else {
[self.view addSubviewWithZoomInAnimation:self.viewToZoom duration:1.0 option:0];
isShown = YES;
}
}
UIView+Animation.m
- (void) addSubviewWithZoomInAnimation:(UIView*)view duration:(float)secs option:(UIViewAnimationOptions)option {
CGAffineTransform trans = CGAffineTransformScale(view.transform, 0.01, 0.01);
view.transform = trans; // do it instantly, no animation
[self addSubview:view];
// now return the view to normal dimension, animating this tranformation
[UIView animateWithDuration:secs delay:0.0 options:option
animations:^{
view.transform = CGAffineTransformScale(view.transform, 100.0, 100.0);
}
completion:^(BOOL finished) {
NSLog(#"done");
} ];
}
- (void) removeSubviewWithZoomOutAnimation:(UIView*)view duration:(float)secs option:(UIViewAnimationOptions)option {
// now return the view to normal dimension, animating this tranformation
[UIView animateWithDuration:secs delay:0.0 options:option
animations:^{
view.transform = CGAffineTransformScale(view.transform, 0.01, 0.01);
}
completion:^(BOOL finished) {
[view removeFromSuperview];
}];
}
Thanks,
Newton

Newton, when removeSubviewWithZoomOutAnimation ends the view.transform is an affine transform that scaled the view's original size down to 0.01. The problem is that when you call addSubviewWithZoomInAnimation the second time you're again scaling down by 0.01, but now the view.transform will be scaled down to 0.0001, which is not what you're looking for.
Simply add view.transform = CGAffineTransformIdentity; at the beginning of both animations like this:
- (void) addSubviewWithZoomInAnimation:(UIView*)view duration:(float)secs option:(UIViewAnimationOptions)option {
view.transform = CGAffineTransformIdentity;
CGAffineTransform trans = CGAffineTransformScale(view.transform, 0.01, 0.01);
view.transform = trans; // do it instantly, no animation
[self addSubview:view];
// now return the view to normal dimension, animating this tranformation
[UIView animateWithDuration:secs delay:0.0 options:option
animations:^{
view.transform = CGAffineTransformScale(view.transform, 100.0, 100.0);
}
completion:^(BOOL finished) {
NSLog(#"done");
} ];
}
- (void) removeSubviewWithZoomOutAnimation:(UIView*)view duration:(float)secs option:(UIViewAnimationOptions)option {
view.transform = CGAffineTransformIdentity;
// now return the view to normal dimension, animating this tranformation
[UIView animateWithDuration:secs delay:0.0 options:option
animations:^{
view.transform = CGAffineTransformScale(view.transform, 0.01, 0.01);
}
completion:^(BOOL finished) {
[view removeFromSuperview];
}];
}
I also suggest you to pass the UIViewAnimationOptionBeginFromCurrentState UIViewAnimationOptions which improves the animation result when quickly zooming in and out.
Hope this helps!

Related

Custom UIView doesn't get removed from superview when loaded again while animating

The question explains it all actually.
I load a custom UIView on top of my current view, animated, using this code:
- (void)showView
{
self.blurView.alpha = 0.f;
[UIView animateWithDuration:2.0 delay:0.0 options:UIViewAnimationOptionAllowUserInteraction animations:^
{
self.blurView.alpha = 1.f;
} completion:^(BOOL finished) {
[UIView animateWithDuration:2.0 delay:0.0 options:UIViewAnimationOptionAllowUserInteraction animations:^
{
self.blurView.alpha = 0.f;
} completion:nil];
}];
}
It works, but when I perform -(void)showView again while it is still animating, the custom view doesn't get removed from the screen.
It just stays like this:
I figured out what the problem was.
blurView is a public variable and every time I did -(void)showView it used the same variable, setting the alpha to 0.f just once, thus never changing the alpha of the first show.
I declared the variable blurView in the method itself and now it works because every blurView gets it's own pointer.
-(void)someMethod
{
//Create a live blur view
FXBlurView *blurView = [[FXBlurView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
blurView.center = CGPointMake(self.view.window.frame.size.width / 2, self.view.window.frame.size.height / 2);
blurView.layer.cornerRadius = 20.f;
[self.view.window addSubview:blurView];
[self showView:(blurView)];
}
- (void)showView:(FXBlurView *)blurView
{
//Make full transparent before showing
blurView.alpha = 0.f;
//Start animation
[FXBlurView animateWithDuration:1.0 delay:0.0 options:UIViewAnimationOptionAllowUserInteraction animations:^
{
blurView.alpha = 1.f;
} completion:^(BOOL finished) {
if (finished)
{
//End animation
[FXBlurView animateWithDuration:1.0 delay:0.0 options:UIViewAnimationOptionAllowUserInteraction animations:^
{
blurView.alpha = 0.f;
} completion:nil];
}
}];
}
You should add to the top of your function this line:
[self.view.layer removeAllAnimations];
It will remove all of the active animations.
It doesn't work because you have implemented a delay, use animation block with delay - it will create animation keys that could be removed with this function above.
[UIView animateWithDuration:0.3 delay:0.0
options:UIViewAnimationOptionAllowUserInteraction
animations:^
{
// ...
} completion:NULL];

Custom Map Callout Animation

I have to create custom MKMapView annotations, which look almost the same as the ones iOS provides, but have different color (white) and slightly different shape.
My first attempt was to prevent opening the original black UIAnnotationViews and in AnnotationView's setSelected:animated: added a new subview to the same UIAnnotationView. I have animated this view after adding it to the superview. This had only one problem: my custom button in the annotation was not clickable.
After this I've found this excellent example:
https://github.com/tochi/custom-callout-sample-for-iOS
This adds a new CalloutAnnotation to the map when the user clicks on a PinAnnotation. PinAnnotations have no AnnotationViews, only CalloutAnnotations do.
This works fine, except that I can't figure out how to do the iOS-like initial zooming animation on the annotation views when they are created.
The animation I want to use is the following (found here on SO and worked fine with my first attempt):
- (void)animateCalloutAppearance:(CalloutAnnotationView *)annotaitonView
{
self.endFrame = annotaitonView.frame;
CGFloat scale = 0.001f;
annotaitonView.transform = CGAffineTransformMake(scale, 0.0f, 0.0f, scale, [self xTransformForScale:scale andAnnotation:annotaitonView], [self yTransformForScale:scale]);
[UIView animateWithDuration:0.075f delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
CGFloat scale = 1.2f;
annotaitonView.transform = CGAffineTransformMake(scale, 0.0f, 0.0f, scale, [self xTransformForScale:scale andAnnotation:annotaitonView], [self yTransformForScale:scale]);
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.1 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
CGFloat scale = 0.90;
annotaitonView.transform = CGAffineTransformMake(scale, 0.0f, 0.0f, scale, [self xTransformForScale:scale andAnnotation:annotaitonView], [self yTransformForScale:scale]);
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.075 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
CGFloat scale = 1.0;
annotaitonView.transform = CGAffineTransformMake(scale, 0.0f, 0.0f, scale, [self xTransformForScale:scale andAnnotation:annotaitonView], [self yTransformForScale:scale]);
} completion:nil];
}];
}];
}
#pragma mark - The helper methods
- (CGFloat)relativeParentXPosition:(CalloutAnnotationView *)annotationView {
return annotationView.bounds.size.width / 2.0f;
}
- (CGFloat)xTransformForScale:(CGFloat)scale andAnnotation:(CalloutAnnotationView *)annotationView {
CGFloat xDistanceFromCenterToParent = self.endFrame.size.width / 2.0f - [self relativeParentXPosition:annotationView];
CGFloat transformX = (xDistanceFromCenterToParent * scale) - xDistanceFromCenterToParent;
return transformX;
}
- (CGFloat)yTransformForScale:(CGFloat)scale {
CGFloat yDistanceFromCenterToParent = self.endFrame.size.height / 2.0f;
CGFloat transformY = yDistanceFromCenterToParent - yDistanceFromCenterToParent * scale;
return transformY;
}
I've found the answer on this blog: http://blog.asynchrony.com/2010/09/building-custom-map-annotation-callouts-part-1/
The tricky part is that you have to do the animation in the CalloutAnnotationView's didMoveToSuperView :)
- (void)didMoveToSuperview
{
[self animateCalloutAppearance:self];
}
I hope it helps somebody else :)

How to add multiply animation to the view in objective c?

I want to add multiple animations to the view. I just can add one,... I do not want to concatenate
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:kAnimationDuration];
//self.square.bounds = CGRectMake(0, 0, self.square.bounds.size.height, 200);
//self.transform = CGAffineTransformMakeScale(2, 1);
CGAffineTransform scaleTrans1 = CGAffineTransformMakeScale(2, 1);
self.transform = scaleTrans1;
[UIView commitAnimations];
You can use animateWithDuration (in any of its variations) from UIView, as long as the properties you are trying to animate are actually animatable (view UIView / Animations).
For example:
[UIView animateWithDuration:1.0f
animations: ^ {
self.square.bounds = CGRectMake(0, 0, self.square.bounds.size.height, 200);
self.transform = CGAffineTransformMakeScale(2, 1);
}];
Hope it helps!
I did like this and its working
- (void)drawRect:(CGRect)rect
{
[UIView animateWithDuration:4.0f animations:^{
self.transform = CGAffineTransformMakeScale(2, 1);
} completion:^(BOOL finished){
[UIView animateWithDuration:4.0f animations:^{
self.transform = CGAffineTransformMakeScale(0.75, 1);
} completion:^(BOOL finished){
[UIView animateWithDuration:4.0f animations:^{
self.transform = CGAffineTransformMakeScale(2, 1);
} completion:^(BOOL finished) {
[UIView animateWithDuration:4.0f animations:^{
self.transform = CGAffineTransformMakeScale(0.75, 1);
}];
}];
}];
}];
}

Resize view right-to-left with animation on iOS

I would like to resize UIView from right side to left (opposite).
Now I have view with rect like this: CGRectMake(100.f, 0.f, 100.f, 100.f);
[UIView animateWithDuration:0.5 animations:^{
view.frame = CGRectMake(0.f, 0.f, 200.f, 100.f);
}];
The problem is that animation is not nice. It bounces to the right (gets bigger) and than moves to location 0.0,0.0.
I would like to achieve the same effect like when resizing from left to right.
EDIT: code
- (void)resizeSearchBar:(int)type
{
//resize - bigger
if (type == 1) {
[UIView animateWithDuration:1.0 animations:^{
self.searchBar.frame = CGRectMake(0.f, 0.f, 280.f, 44.f);
}];
}
//resize - smaller
else {
[UIView animateWithDuration:1.0 animations:^{
self.searchBar.frame = CGRectMake(95.f, 0.f, 185.f, 44.f);
}];
}
}
EDIT 2
I've also tried to change View properties in IB like that:
Still no luck...
Got it to work with the hint from this answer: Can't animate the frame or bounds of a UISearchBar
The trick is to call [searchBar layoutSubviews]; in your animation block after setting the frame.
Here is what I got to work in my sample:
- (IBAction)resizeButtonTapped:(id)sender {
//resize - bigger
if (searchBar.frame.origin.x == 95) {
[UIView animateWithDuration:1.0 animations:^{
self.searchBar.frame = CGRectMake(0.f, 0.f, 280.f, 44.f);
[searchBar layoutSubviews];
}];
}
//resize - smaller
else {
[UIView animateWithDuration:1.0 animations:^{
self.searchBar.frame = CGRectMake(95.f, 0.f, 185.f, 44.f);
[searchBar layoutSubviews];
}];
}
}
I think this is useful to you just see bellow demo link...
https://github.com/ipup/PPRevealSideViewController?_tmc=UFw1P_Ai9brJd4WEpSlPbNrXBWOvsYZ6gNPi_derQik
i hope this help you..
:)
edited...
[UIView animateWithDuration:0.5
delay:4.0
options: UIViewAnimationOptionTransitionCrossDissolve
animations:nil
completion:^{
view.frame = CGRectMake(0.f, 0.f, 200.f, 100.f);}];
not sure but try this and also use different Animation like "UIViewAnimationOptionTransitionCrossDissolve",etc....
hope this help you....
It bounces because the duration is much less!!
Increase the duration ..and i think it will make it more clear how it animates
K try this
[UIView animateWithDuration:1.0
delay:0.0
options:UIViewAnimationCurveEaseInOut
animations:^ {
self.searchBar.frame = CGRectMake(0.f, 0.f, 280.f, 44.f);
}
completion:^(BOOL finished) {
}];
Chk here for Options

iOS - Animation effects - Image pop-in

I'd like to have an image in my iphone app "pop-in" on screen rather than just appearing. By "pop-in" I mean that it would grow from a small dot to its actual size. For reference, this is exactly the same as the "pop" animation effect in Keynote.
I'm completely new to iOS animations, so if someone could point me in the direction on the animation effects I would need to use, it would be greatly appreciated.
Thanks
Brian
UPDATE
I've added this code from the suggestions below. This works but it scales my image down, rather than up. I know that is because I have 0.01 as the transform scale size, but I would like to know how I can start out with an image of size 0.0 and scale up to 1. Is it just a matter to setting the size of my image to 0?
Thanks
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration: 0.2];
image.transform = CGAffineTransformMakeScale(0.01, 0.01);
[UIView setAnimationDelegate:self];
[UIView commitAnimations];
The effect you’re looking for is something like this:
// instantaneously make the image view small (scaled to 1% of its actual size)
view.transform = CGAffineTransformMakeScale(0.01, 0.01);
[UIView animateWithDuration:0.2 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
// animate it to the identity transform (100% scale)
view.transform = CGAffineTransformIdentity;
} completion:^(BOOL finished){
// if you want to do something once the animation finishes, put it here
}];
if you want something like Facebook does on liking any post then use this
-(void)animateButton:(UIButton *)sender{
UIButton * btn = (UIButton *)sender;
[UIView animateWithDuration:0.3/1.5 animations:^{
btn.transform = CGAffineTransformScale(CGAffineTransformIdentity, 1.4, 1.4); // scales up the view of button
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.3/2 animations:^{
btn.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.7, 0.7);// scales down the view of button
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.3/2 animations:^{
btn.transform = CGAffineTransformIdentity; // at the end sets the original identity of the button
}];
}];
}];}
just call this method when you want to animate the view
if you have text and image on the button and you just want to animate the image of the button then just replace "btn" with "btn.imageView" , this will just produce animation on the image view property of the button.
Hope it helps
All the best.
You have to animate the frame of the view, to shrink it from zero to the final state.
This can be done for example with UIView block animation.
So for example start with your view as an IBOutlet property self.myView with the final size and position, but set the hidden flag.
Then when you want it to appear use the following:
// Save old frame as final stater and set it to zero size for the start of the animation
// But keep the same center position, so it just grows and don't move around
CGRect oldFrame = self.myView.frame;
CGRect oldCenter = self.myView.center;
self.myView.frame = CGRectZero;
self.myView.center = oldCenter;
self.myView.hidden = NO;
NSTimeInterval duration = 0.3;
[UIView animateWithDuration:duration delay:0.0 options:UIViewAnimationOptionAllowUserInteraction animations:^{
// New position and size after the animation should be the same as in Interface Builder
self.myView.frame = oldFrame
}
completion:^(BOOL finished){
// You can do some stuff here after the animation finished
}];
Swift 2.0 version
view.transform = CGAffineTransformMakeScale(0.01, 0.01);
UIView.animateWithDuration(0.2, delay: 0, options: .CurveEaseOut, animations: { () -> Void in
// animate it to the identity transform (100% scale)
self.view.transform = CGAffineTransformIdentity;
}) { (finished) -> Void in
// if you want to do something once the animation finishes, put it here
}
For that you will have to use a simple UIView
Add the UIview to your current view.
- (void) initPopUpView
{
popup.alpha = 0;
popup.frame = CGRectMake (160, 240, 0, 0);
[self.view addSubview:popup];
}
- (void) animatePopUpShow
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3];
[UIView setAnimationDelegate:self];
[UIView setAnimationWillStartSelector:#selector(initPopUpView)];
popup.alpha = 1;
popup.frame = CGRectMake (20, 40, 300, 400);
[UIView commitAnimations];
}