I saw this thread but the solution is not what I'm looking for.
I would like to pop up a UIView with an animation similar to how an app appears from the SpringBoard (it seems it comes closer) and make it disappear moving it away.
I've tried to animate the frame, but the effect is that the content is not resized: unfortunately I cannot assign constraints to the content of the view; the result should be like if the view is shown with the correct sizes and only the "graphics context" is resized.
Help!
This starts at 10% the size and turns to 100 % of the views size
view.transform = CGAffineTransformScale(view.transform, 0.1, 0.1);
[UIView animateWithDuration:0.35 animations:^{
view.transform = CGAffineTransformScale(view.transform, 1.0, 1.0);
} completion:^(BOOL finished) {
}];
also remember to #import <QuartzCore/QuartzCore.h>
You can animate the transform.scale and opacity of the view's layer. See this answer for details: https://stackoverflow.com/a/3463362/550177
Related
I have a page in my app in which there is user's profile pic in a circle as its there in Twitter profile page.
I have to add a functionality such that when I tap on it, the image should expand. Animation needs to be added in such a way that a new bigger circle should slowly appear from the centre of the smaller circle and reach the centre of the screen.
Any ideas as to how this can be implemented?
Try UIView Animation block with changing bigger circle's position, size, alpha, and corner radius (if required).
Place your bigger circle (with smaller size initially) on top of smaller circle and hide it initially. Then before animation, un-hide it and animate using a block like this:
[UIView animateWithDuration:1.0 animations:^{
// set bigger circle destination position i.e. centre of screen
// set bigger circle final size
// set other properties like alpha, corner radius etc
} completion:nil];
Use CATransform3DScale transform and UIView Animation
CATransform3D avatarTransform = CATransform3DIdentity;
avatarTransform = CATransform3DScale(avatarTransform, avatarScaleFactor,avatarScaleFactor, 0);
[UIView animateWithDuration:1.0 animations:^{
//Change the frame to reach the center of screen
self.avatar.layer.transform = headerTransform
} completion:nil]
You can simply use CGAffineTransformScale and scale your ImageView inside UIView's animateWithDuration block.
imgV.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.0, 0.0);
[UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationOptionCurveEaseInOut
animations:^{
imgV.transform = CGAffineTransformScale(CGAffineTransformIdentity, 1.0, 1.0);
}
completion:^(BOOL finished) {
NSLog(#"done");
}];
For further references you can look into these Stackoverflow questions :
Animate a UIImageView
iOS View Transform Animation
I'm trying to find a reason why animation of UIView transform property looks different in iOS 8 than iOS 6/7.
For a simple example, prior to iOS 8:
myView.transform = CGAffineTransformRotate(CGAffineTransformIdentity, 1.57);
[UIView animateWithDuration:5 animations:^{
myView.transform = CGAffineTransformTranslate(plane.transform, 100, 0);
}];
gives expected result, "myView" is rotated 90 degrees and moves down, but in iOS8 when translation is animated it starts at a point that I couldn't find explanation for (which breaks the animation).
Does anyone know the explanation for it? Thanks in advance!
CGAffineTransformIdentity behaves differently on ios7 and ios8. This has to do with auto-layout and size classes. The solution is to remove constraints that conflict with the animation on ios7.
// solve the constraint-animation problem
if(NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1) {
// iOS7 remove constraints that conflict with animation
if (self.centerYAlignment != nil) {
self.view.removeConstraint(self.centerYAlignment) //is an IBOutlet
}
} else {
// iOS8 constraint animations are fine
}
I think the reason is just iOS8 bug, but I use CAAnimation instead, and it works as expected on iOS8.
I had problems with jerky rotation transform in iOS7 as well. Solved this by nesting my rotated view inside a container and centering the rotated view inside.
I'm also experiencing the same issue with scaling. I guess it could be the same with rotation. Could you try this?
myView.transform = CGAffineTransformConcat(myView.transform , CGAffineTransformMakeRotate(1.57));
[UIView animateWithDuration:5 animations:^{
myView.transform = CGAffineTransformTranslate(plane.transform, 100, 0);
}];
Maybe it's also necessary to use CGAffineTransformMakeTranslate and CGAffineTransformConcat that as well, I'm not sure.
The worst part about this is: You would have to do if/else on iOS versions, because this would look weird on iOS 7. I hope this is getting fixed by Apple before or with iOS 8 release.
I agree with Pbk that it has to do with size classes in io8. uiviewcontrollers need to be resized with uitraitcollections depending on the device orientation. Otherwise, you get a uiviewcontroller in portrait mode, while the phone is in landscape mode, when you try to rotate it. So the correct steps are to rotate AND override uitraitcollections
This isn't entirely related, but I was struggling with CGAffineTransformScale not working at all on iOS7 in a fairly complicated animation. It turns out my problem was iOS7 cannot calculate CGAffineTransformScale with CGAffineTransformRotate at the same time. In iOS7, the last animation call you make is the only one that gets animated, so only the rotation was occurring. This bug is fixed in iOS8.
My solution is to simplify my animation for iOS7, only turning on the fancy stuff in iOS8:
//Pre-animation setup:
CGFloat radians = (M_PI/180) * (-15); //Get a human-readable number in degrees
self.badgeImage.alpha = 0; //Start the image as invisible
self.badgeImage.transform = CGAffineTransformScale(self.badgeImage.transform, 1.5, 1.5); //Start the image as scaled bigger than normal
if(NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1) { //See below. We will not be rotating the image in iOS7
self.badgeImage.transform = CGAffineTransformRotate(self.badgeImage.transform, radians); //Rotate the image if iOS8
}
//Animation Pieces:
//Fade in
[UIView animateWithDuration: 0.5
delay:0
options:0
animations:^{
self.badgeImage.alpha = 1.0f; //Return image to opaque
}
completion:NULL];
//Scale with bounce
[UIView animateWithDuration: 1.1
delay:0
usingSpringWithDamping:0.3 //Not as good as Android's bounce interpolator, but I'll take it
initialSpringVelocity:-1.0f //A negative velocity here makes the animation appear more like gravity than spring
options:0
animations:^{
self.badgeImage.transform = CGAffineTransformScale(self.badgeImage.transform, 0.67, 0.67); //Return image to its original size. These arguments are relative to its current scale.
}
completion:NULL];
//Rotation
if(NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1) { //This second animation call negates the first one on iOS7, so remove it.
[UIView animateWithDuration: 0.9
delay:0
options:UIViewAnimationOptionCurveEaseOut
animations:^{
self.badgeImage.transform = CGAffineTransformRotate(self.badgeImage.transform, (radians * -1)); //Rotate the image back to its original orientation if iOS8
}
completion:NULL];
}
Of course, you can still combine multiple effects in iOS7 if you use the confusingly-named CGAffineTransformMakeScale() function. For instance, in the pre-animation setup, you can set both a rotation AND a scale, then set call CGAffineTransformMakeScale(1,1) to reset the image to its original metrics (MakeScale's arguments are specific, not relative - even more confusing!). This isn't always preferable, such as my example above where "bouncing" the animation would also bounce the rotation.
I have the following super simple animation, I'm basically rotating a view 2 radians from its original angle/center, it rotates fine my only misunderstanding is why does the view move from its original position when the rotation occurs.
[UIView animateWithDuration:1.0 animations:^{
self.someView.transform = CGAffineTransformMakeRotation( 2 );
}];
Why does the view moves when rotated with the code above?
I'm currently trying to discern the information in the CGAffineTransform Reference.
Understanding the anchor point.
I found this threads but it doesn't show a concrete answer.
Why rotating imageView, it changes position?
Thanks a lot
You need to set the anchor point of your view to rotate around.
self.somview.layer.anchorPoint = CGPointMake(0.5, 0.5);
Then start the rotation.
From Apple documentations
#property(nonatomic) CGAffineTransform transform Changes to this
property can be animated. Use the beginAnimations:context: class
method to begin and the commitAnimations class method to end an
animation block. The default is whatever the center value is (or
anchor point if changed)
Link: https://developer.apple.com/library/ios/documentation/GraphicsImaging/Reference/CALayer_class/Introduction/Introduction.html#//apple_ref/occ/instp/CALayer/anchorPoint
image from here http://www.raywenderlich.com/9864/how-to-create-a-rotating-wheel-control-with-uikit
- As you see the anchor point is the point with the value from 0.0 - 1.0 for X and Y
when you rotate the rotation will be around these points
NOTE: you need to import QuartzCore
I am adding another answer due to #fs_tigre request. The problem is with the auto layouts in your xib file, unfortunately is it unknown why that affects the transform.
Now here is the steps I did to solve the issue:
1- first you need to get rid off your auto layout (yes, you have to)
uncheck Use Autolayout
2- remove all constraints and autoresizing masks for your view that will be rotated, as in the screenshot
(Here I have my blue box, see on the right autoresizing, nothing is selected)
I have made some changes for your rotation's code
self.someView.layer.anchorPoint = CGPointMake(0.5, 0.5);
// one degree = pi/180. so...
// rotate by 90
CGFloat radians = (M_PI/180) * 90;
[UIView animateWithDuration:1.0 animations:^{
self.someView.transform = CGAffineTransformRotate(self.someView.transform, radians);
}];
Click rotate and see the magic :)
The "anchor" of CGAffineTransformMakeRotation is the X,Y of the view. You can try this:
CGPoint center = self.someView.center;
[UIView animateWithDuration:1.0 animations:^{
self.someView.transform = CGAffineTransformMakeRotation( 2 );
self.someView.center = center;
}];
- (void)startAnimation {
//reverse - shrinking from full size
if (_reversed == YES) {
//self.transform = CGAffineTransformMakeScale(1.0, 1.0);
[UIView animateWithDuration:1.0f delay:0.0f options:UIViewAnimationOptionCurveLinear animations:^{
self.transform = CGAffineTransformMakeScale(0.1, 0.1); //this line does it instantly
self.alpha = 0;
} completion:^(BOOL finished) {
[self removeFromSuperview];
}];
} else {
//non reverse - expanding from middle
self.transform = CGAffineTransformMakeScale(0.001, 0.001);
[UIView animateWithDuration:1.0f delay:0.0f options:UIViewAnimationOptionCurveLinear animations:^{
self.transform = CGAffineTransformMakeScale(1.0, 1.0);
self.alpha = 0;
} completion:^(BOOL finished) {
[self removeFromSuperview];
}];
}
}
The non reverse piece of code does work fine as I expect, however when I do the _reversed == YES bit, the transformation inside the animation block happens instantly. If I comment that line of code, then the view stays the right size, but if i uncomment it then it shrinks instantly but the alpha still does the fade animation. Why does this happen?
Edit: I figured out what happened but I don't know how to fix it. The view does do the animation, only the size of the view changes instantly but it still 'slides' into the centre as if it is shrinking (what you see is just a small rectangle sliding to the middle as if it's the top left corner of the object). If I scale the view to 2 first, then scale down to 1 the animation works fine, its only when going from 1 to a decimal number that it doesn't work. Also I used draw rect to create an object with core graphics and the transform problem affects that, but not the actual frame if a set background colour.
I was running into a similar issue, where the position of the view would suddenly jump before animating in a change of transform with CGAffineTransformMakeScale. I noticed that the size of the "jump" seemed to be proportional to the scaling that would occur later in the animation.
I could fix this problem by finding that in a viewWillLayoutSubviews() override, I was setting the frame of the view being animated. As a rule, don't set the frames of views that will have a non-identity transform. So in the viewWillLayoutSubviews() override, I set the view's bounds and layer.position instead and now the animation is smooth as silk.
I have my subviews inside my view with the appropriate AutoresizingMasks so that they accommodate accordingly when the view's size changes.
My issue comes when the view is shrinked too much, or even not that much. The subviews seems to forget their original position and begin to place in weird positions or scale too much or too less.
The original requirement is to "Shrink a view" to its center and then to "Popit up" like a balloon, from the ~=zero-size to the original frame size.
I have shrinked and popped up views before without much problem in other projects I don't know if it's because the view is more complex now
Well, as I said, I have done this before so I just checked my other project and I found my problem, I post the answer here to share the knowledge for anyone interested, as I couldn't google this moments before.
The problem is that shrinking or growing views using their frame is not the correct method to do this.
Bad example:
[UIView animateWithDuration: 0.4 delay:0 options: UIViewAnimationCurveEaseInOut animations:^{
self.frame = CGRectMake(frame.origin.x + frame.size.width/2, frame.origin.y + frame.size.height/2, 10, 10);
} completion: nil];
instead, transforms should be used:
self.transform = CGAffineTransformScale(CGAffineTransformIdentity, 1, 1);
[UIView animateWithDuration: 0.4 delay:0 options: UIViewAnimationCurveEaseInOut animations:^{
self.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.001, 0.001);
} completion: nil];
The above places the elements where they are supposed to after I shrink and grow my views, taking into account that is is only for animation purposes.
Hope it helps.