Combining animations on UIView and subiview's CALayer? - iphone

I'm animating a UIView transition like so:
UIView *areaView = areaController.view;
[areaController viewWillAppear:YES];
UIView *subView = self.customView.subView;
UIButton *button = customView.button; // button is a subview of customView.subView
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:subView cache:YES];
[button removeFromSuperview];
[subView addSubview:areaView];
[areaController viewDidAppear:YES];
[UIView commitAnimations];
[self.areaController start]; // areaController starts the animation of the CALayer, see below
This flips the new view, areaView from "behind" the button just fine, but in areaView there's another subview which is animating it's CALayer:
CATransform3D rotate = CATransform3DMakeRotation(angle, 1, 0, 0);
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"transform"];
animation.toValue = [NSValue valueWithCATransform3D:rotate];
animation.duration = .08;
animation.delegate = self;
animation.fillMode = kCAFillModeForwards;
animation.removedOnCompletion = NO;
[layer addAnimation:animation forKey:#"transform"];
My question is:
How do I make both these animations animate in parallell?
Currently, the animation on the CALayer starts when calling [self.areaController start];, but the result is not visible until the transition on the superview is finished. Should I somehow use an animation group with the UIView's layer?

I think you can't do these at the same time. What you can do is do the first animation also using the CATransform3D, then they will occur at the same time.
This is an old post though so maybe you've already solved the issue.

Related

Want create a View that come from upperside at some position

I have created View which displays at position (0, 0, 320, 100). Now I want to make that view to come from upperside and to be set at given position I have tried this.
CATransition *transition = [CATransition animation];
transition.duration = 1.0;
transition.type = kCATransitionFromTop; //choose your animation
[bGView.layer addAnimation:transition forKey:nil];
[self.view addSubview:bGView];
But it did not worked for me.
You can adjust frames of your view in animation blocks
First add your view as subview
[self.view addSubview:bGView];
and give it a frame outside the visible screen area
bGView.frame = CGRectMake(0,-150,320,100);
and then fire animation to bring it from upside
[UIView animateWithDuration:2.0
animations:^{
bGView.frame = CGRectMake(0,0,320,100);
}
completion:^(BOOL finished){
;
}];
Everything is ok. Except a fact that animation should be added in superview, so it should be like:
[self.view.layer addAnimation:transition forKey:nil];
You can try view block animation
[UIView animateWithDuration:0.7f animations:^{
bGView.frame = CGRectMake(0.0f, 200.0f, 320.0f, 100.0f);//Some frame
}];

Animation, like when you delete from iPhone Photo Gallery

I try to implement the animation:
when you enter iPhone Gallery, press the image, you see full-screen image. Below you can see toolbar with trash button. When you press this button, the image is being deleted with animation.
I try to implement this, but I don't know, how to implement the transform of image, apple use.
This is the best, I could do:
[UIView transitionWithView:self.view duration:0.1 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
[self.view addSubview:scrollImageView];
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionAllowUserInteraction animations:^{
CGRect frame = scrollImageView.frame;
frame.size = CGSizeMake(frame.size.width * 0.75, frame.size.height * 0.75);
frame.origin = CGPointMake((size.width - frame.size.width) / 2, (size.height - frame.size.height) / 2);
scrollImageView.frame = frame;
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionAllowUserInteraction animations:^{
CGRect frame = scrollImageView.frame;
frame.size = CGSizeMake(frame.size.width * 0.05, frame.size.height * 0.05);
frame.origin = CGPointMake(size.width, size.height);
scrollImageView.frame = frame;
CGAffineTransform transform = scrollImageView.transform;
CGAffineTransform rotatedTransform = CGAffineTransformRotate(transform, 45 * 3.14 / 180);
scrollImageView.transform = rotatedTransform;
} completion:^(BOOL finished) {
[scrollImageView removeFromSuperview];
}];
}];
}];
Thank you in advance.
Update
As I understand, I can't do this animation with Core-Animation, but may anyone can advice me the animation the most simular to iPhone Gallery animation, but without using OpenGL?
You can use following example for this animation:
UIView *senderView = (UIView*)sender;
CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:#"transform"];
anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
anim.duration = 0.125;
anim.repeatCount = 1;
anim.autoreverses = YES;
anim.removedOnCompletion = YES;
anim.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.2, 1.2, 1.0)];
//[senderView.layer addAnimation:anim forKey:nil];
UIBezierPath *movePath = [UIBezierPath bezierPath];
[movePath moveToPoint:icon.center];
[movePath addQuadCurveToPoint:senderView.center
controlPoint:CGPointMake(senderView.center.x, icon.center.y)];
CAKeyframeAnimation *moveAnim = [CAKeyframeAnimation animationWithKeyPath:#"position"];
moveAnim.path = movePath.CGPath;
moveAnim.removedOnCompletion = YES;
CABasicAnimation *scaleAnim = [CABasicAnimation animationWithKeyPath:#"transform"];
scaleAnim.fromValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];
scaleAnim.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(0.1, 0.1, 1.0)];
scaleAnim.removedOnCompletion = YES;
CABasicAnimation *opacityAnim = [CABasicAnimation animationWithKeyPath:#"alpha"];
opacityAnim.fromValue = [NSNumber numberWithFloat:1.0];
opacityAnim.toValue = [NSNumber numberWithFloat:0.1];
opacityAnim.removedOnCompletion = YES;
CAAnimationGroup *animGroup = [CAAnimationGroup animation];
animGroup.animations = [NSArray arrayWithObjects:moveAnim, scaleAnim, opacityAnim, nil];
animGroup.duration = 0.5;
[icon.layer addAnimation:animGroup forKey:nil];
I have modified the code, you have to perform following changes in it, set the sender view as self.view, and change the ending point of animation (which is currently senderView.center) according to your requirement
I know its a bit late. But, you should check Ciechan's solution named BCGenieEffect. Can be found here. Its pure Core Animation and very easy to understand. I think that's what you are looking for.
Good luck
At this point the exact animation you are talking about cannot be done using Core Animation or UIKit. You would need to use OpenGL and apply the image as a texture and do your animation in there.
I think you are talking about the "suck" transition animation.
It is possible to trigger it, but it is a private transition, and Apple may reject your app if you use it.
This code should do it, using a transition code of 103:
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1.0];
[UIView setAnimationTransition: transtionIndex forView:containerView cache:NO];
[containerView addSubview: newView];
[oldView removeFromSuperview];
[UIView commitAnimations];
Or search the net for a Core Image transition called "suckEffect"

How can I make slide down transition animation?

I can see a lot of transition animation: from left to right, right to left, fading, but how can I make transition from the top down to bottom?
Thanks for all help
Try working out this...
Add QuartzCore framework
#import <QuartzCore/QuartzCore.h>
CATransition *transDown=[CATransition animation];
[transDown setDuration:0.5];
[transDown setType:kCATransitionPush];
[transDown setSubtype:kCATransitionFromBottom];
[transDown setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[Boottom_view.layer addAnimation:transDown forKey:nil];
[[self navigationController] presentModalViewController:modalViewController animated:YES];
and hiding it like this:
[self.navigationController dismissModalViewControllerAnimated:YES];
Your could use Core Animation, what sort of object are you using?
Basically, to fade in an object you do this:
[[objectName animator] setOpacity: 1];
Remember you first need to set the opacity to 0 etc. before the animation begins.
Hope this is what your wanting.
You set your view frame to it's starting position offscreen and then your bring your frame into position with some animation.
CGRect originalFrame = [detailsView frame];
CGRect offscreenFrame = originalFrame;
offscreenFrame.origin.y -= offscreenFrame.size.height;
detailsView.frame = offscreenFrame; //Send the frame above screen
//Add view here if necessary to an unscrew view
// [aSuperView addSubview:detailsView];
[UIView beginAnimations:#"BringIn" context:nil];
[UIView setAnimationDuration:.3];
[UIView setAnimationDelegate:self];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
detailsView.frame = originalFrame
[UIView commitAnimations];

How can I rotate a UIButton continuously and be able to stop it?

I want to rotate a UIButton continuously as a means of indicating that an app is recording something. Is this a good idea. I also want to be able to stop this continuous rotation.
How would I use animation to do this?
Use the UIView animation method:
animateWithDuration:delay:options:animations:completion:
and use the option UIViewAnimationOptionRepeat
For example for a UIButton * outlet named button:
- (void)viewDidLoad
{
[super viewDidLoad];
[UIView animateWithDuration:2.0 delay:0.0 options:UIViewAnimationOptionRepeat | UIViewAnimationOptionCurveLinear animations:^{
CGAffineTransform transform = CGAffineTransformMakeRotation(M_PI);
self.button.transform = transform;
} completion:NULL];
}
Since it's going round and round, I just rotate it by pi radians rather than 2pi. you could use any angle you want.
Edit
To stop the animation, just create another animation of a short duration beginning from the current state, e.g.
- (void)stopRotating {
[UIView animateWithDuration:0.1 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionCurveLinear animations:^{
CGAffineTransform transform = CGAffineTransformMakeRotation(M_PI * 0.05);
self.button.transform = transform;
} completion:NULL];
}
This provides a very short animation which overrides the current animation. Note that the angle of the transform is multiplied by 0.05 which is the ratio of 0.1/2.0 which means that the rotational speed for this little segment is the same as the continuous rotational speed.
Try below code that will help you because I run that code successfully.
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[button setTitle:#"Show View" forState:UIControlStateNormal];
button.frame = CGRectMake(80.0, 210.0, 160.0, 40.0);
[self.view addSubview:button];
CABasicAnimation *halfTurn;
halfTurn = [CABasicAnimation animationWithKeyPath:#"transform.rotation"];
halfTurn.fromValue = [NSNumber numberWithFloat:0];
halfTurn.toValue = [NSNumber numberWithFloat:((360*M_PI)/180)];
halfTurn.duration = 0.5;
halfTurn.repeatCount = HUGE_VALF;
[[button layer] addAnimation:halfTurn forKey:#"180"];
I had the same problem myself. In the end I made it like that:
#pragma mark Start/StopSpining
-(void)startSpin{
isSpining = YES;
[self Spin];
}
-(void)stopSpin{
isSpining = NO;
}
-(void)spin{
[UIView animateWithDuration:1.0 delay:0 options: UIViewAnimationOptionCurveLinear animations:^{
self.spinCircle.transform = CGAffineTransformRotate(self.spinCircle.transform, M_PI/2);
} completion:^(BOOL finished) {
if (isSpining)
[self spin];
}];
}
Try below extension for swift 3.
extension UIView {
func rotate360Degrees(duration: CFTimeInterval = 3) {
let rotateAnimation = CABasicAnimation(keyPath: "transform.rotation")
rotateAnimation.fromValue = 0.0
rotateAnimation.toValue = CGFloat(M_PI * 2)
rotateAnimation.isRemovedOnCompletion = false
rotateAnimation.duration = duration
rotateAnimation.repeatCount=Float.infinity
self.layer.add(rotateAnimation, forKey: nil)
}
}
For start rotation.
MyButton.rotate360Degrees()
And for Stop.
MyButton.layer.removeAllAnimations()
I suggest you don't rotate the UIButton, just the image you put on the button. Who knows what complications or overhead rotating a rectangular object that can detect touches introduces - what happened if your user somehow taps in the corner of the button and then releases the tap as the button has rotated so that the touch is now outside? Does that register a touch up inside or not?
Anyway, if you want continuous rotation use a block method:
+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion
seems to fit the bill. The complete rotation (2pi) will occur every duration and you cause it to repeat until you stop it using UIViewAnimationOptionRepeat. You can check with completion to see if you should begin another cycle when one animation cycle has ended and you can stop the animation at any time with
[myView.layer removeAllAnimations];
(If you simply want to run it until you stop it then there are other variants of this method without a completion block)
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDelegate:self];
[UIView setAnimationDuration:0.3];
uiButtonObject.transform = CGAffineTransformMakeRotation(M_PI);
[UIView commitAnimations];
M_PI is the radian value of the angle you want to rotate. Run this in a loop and in a different thread. You might also want to run the above using performSelectorInMainThread method as UI changes are not permitted in the UIThread.

addSubview animation

I have main UIView where I display different data. Then I put a button, which displays subview like this:
- (IBAction) buttonClicked:(id)sender
{
UIView *newView = [[UIView alloc] initWithFrame:CGRectMake(25,25,50,20)];
UILabel *newLabel = [[UILabel alloc] initWithFrame:CGRectMake(25,25,50,25)];
newLabel.text = #"some text";
[newView addSubview:newLabel];
[self.view addSubview:newView];
[newLabel release];
[newView release];
}
newView appears fine, but it doesn't animate itself any way, it just appears immediately. How can I add some kind of animation when newView appears? Like zoom or slide down or something like that. Is there some simple code?
[UIView transitionWithView:containerView duration:0.5
options:UIViewAnimationOptionTransitionCurlUp //change to whatever animation you like
animations:^ { [containerView addSubview:subview]; }
completion:nil];
Hi You could use the UIView Animations:
[newView setFrame:CGRectMake( 0.0f, 480.0f, 320.0f, 480.0f)]; //notice this is OFF screen!
[UIView beginAnimations:#"animateTableView" context:nil];
[UIView setAnimationDuration:0.4];
[newView setFrame:CGRectMake( 0.0f, 0.0f, 320.0f, 480.0f)]; //notice this is ON screen!
[UIView commitAnimations];
The SDK will now figure this out for you and animate the view to the positions you gave it.
This works for most properties of UIViews: alpha, scale, bounds, frames, etc.
There are also build in animations as flip and curl:
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight
forView:newView
cache:YES];
[self.navigationController.view addSubview:settingsView.view];
[UIView commitAnimations];
Hope this helps out getting you started:)
Let's do this in swift.
var redView = UIView(frame:CGRectMake(20,20,100,100))
redView.backgroundColor = UIColor.redColor
redView.alpha = 0.0
view.addSubview(redView)
UIView.animateWithDuration(0.25) { () -> Void in
redView.alpha = 1.0
}
Adding a subview cannot be animated by simply putting it in an animateWithDuration block. And it can't be animated using hidden.
link against QuarzCore framework
#import <QuartzCore/QuartzCore.h>
CATransition *transition = [CATransition animation];
transition.duration = 1.0;
transition.type = kCATransitionPush; //choose your animation
[newView.layer addAnimation:transition forKey:nil];
[self.view addSubview:newView];
I found that even with the animation blocks and options, trying to animate addSubview alone would not do anything for me. I found a workaround which is to set the subview's alpha to 0.0, add the subview, and then animate the setting of the alpha from 0.0 to 1.0. This gives me the fade in effect I was looking for.
Hope this helps someone else.
UIView *redView = [[UIView alloc] initWithFrame:CGRectMake(20, 20, 100, 100)];
redView.backgroundColor = [UIColor redColor];
redView.alpha = 0.0;
[self.view addSubview:redView];
[UIView animateWithDuration:0.5 animations:^{
redView.alpha = 1.0;
}];
Swift 5
UIView.transition(with: renderView, duration: 0.25, options: .transitionCrossDissolve, animations: {
self.renderView.addSubview(emojiView)
self.renderView.bringSubviewToFront(emojiView)
}, completion: nil)
in code example renderView is view to what you will add your subView