How can I fade a UIView in while moving it up? - objective-c

I have a UIView and I want to give it an effect that causes it to start with an alpha of 0 and then while moving up 50 pixels animated it also changes to an alpha of 1. How can this be done in Objective-C?

[UIView animateWithDuration:1.0 animations:^{
//here change position and alpha
CGRect newFrame = view.frame;
newFrame.origin.y += 50;
view.frame = newFrame;
view.alpha = 1.0;
} completion:^(BOOL finished) {
//called when animation did finish. do what you want
}];

https://developer.apple.com/library/ios/documentation/windowsviews/conceptual/viewpg_iphoneos/animatingviews/animatingviews.html
Everything about animations.
It's all right there.
//something similar to what you want:
- (IBAction)showHideView:(id)sender
{
// Fade out the view right away
[UIView animateWithDuration:1.0
delay: 0.0
options: UIViewAnimationOptionCurveEaseIn
animations:^{
thirdView.alpha = 0.0;
}
completion:^(BOOL finished){
// Wait one second and then fade in the view
[UIView animateWithDuration:1.0
delay: 1.0
options:UIViewAnimationOptionCurveEaseOut
animations:^{
thirdView.alpha = 1.0;
}
completion:nil];
}];
}

Something like this would do the trick:
UIView *box = [[UIView alloc] initWithFrame:CGRectMake(self.view.center.x, self.view.center.y, 100, 50)];
box.backgroundColor = [UIColor blackColor];
box.alpha = 0.0f;
[self.view addSubview:box];
[UIView animateWithDuration:2.0f
animations:^{
box.alpha = 1.0f;
CGRect frame = CGRectMake(self.view.center.x, self.view.center.y - 100, 100, 50);
[box setFrame:frame];
}];

Related

UILabel animating frame change disregarding delay

I have a UILabel that I show / hide. I want to show the label, pause for a few seconds and hide it. This code ISN'T working. It removes the view as soon as the animation finished (instantly)
-(void) show
{
[UIView animateWithDuration:.5f delay:0.0f
options:UIViewAnimationOptionCurveEaseIn animations:^{
CGRect newFrame = CGRectMake(0.0f, 64.0f, [UIScreen mainScreen].bounds.size.width, 44.0f);
self.frame = newFrame;
} completion:^(BOOL finished){
[self hideAndRemove];
}];
}
-(void) hideAndRemove
{
[UIView animateWithDuration:.5f delay:2.0f
options:UIViewAnimationOptionCurveEaseIn animations:^{
CGRect frame = CGRectMake(0.0f, 64.0f, [UIScreen mainScreen].bounds.size.width, 0.0f);
self.frame = frame;
} completion:^(BOOL finished){
// nothing
}];
}
However, if I try some other animation on the frame, the delay works and the frame change is animated:
-(void) show
{
[UIView animateWithDuration:.5f delay:0.0f
options:UIViewAnimationOptionCurveEaseIn animations:^{
CGRect newFrame = CGRectMake(0.0f, 64.0f, [UIScreen mainScreen].bounds.size.width, 44.0f);
self.frame = newFrame;
} completion:^(BOOL finished){
[self hideAndRemove];
}];
}
-(void) hideAndRemove
{
[UIView animateWithDuration:.5f delay:2.0f
options:UIViewAnimationOptionCurveEaseIn animations:^{
CGRect frame = CGRectMake(0.0f, 64.0f, [UIScreen mainScreen].bounds.size.width, 250.0f);
self.frame = frame;
} completion:^(BOOL finished){
// nothing
}];
}
I don't know what the problem might be, but I think it comes from the frame height who shouldn't be set to 0.
Why not using [UILabel setAlpha:0] to hide your label, and [UILabel setAlpha:1] to show it back ? It seems cleaner than changing its frame height to 0, and it animates nicely.

How to fade in and fade out a label. continuously

In my Xcode project I have put a label on an xib.
I want to fade the label in and out continuously until the user taps the screen. When this happens I want a new view to appear.
Can anyone suggest how to do the fade-in/out?
Instead of nesting blocks and manually restarting your animations, you can use the option pair UIViewAnimationOptionAutoreverse | UIViewAnimationOptionRepeat to tell Core Animation you want the label to fade in and out continuously.
- (void)startAnimatingLabel
{
self.label.alpha = 0;
[UIView animateWithDuration:1
delay:0
options: UIViewAnimationOptionAutoreverse | UIViewAnimationOptionRepeat
animations:^{
self.label.alpha = 1;
} completion:nil];
}
To stop the animations from running, just remove them from the label's layer.
- (IBAction)tap:(UITapGestureRecognizer *)sender
{
[self.label.layer removeAllAnimations];
self.label.alpha = 0;
[self presentNewView];
}
EDIT: A less abrupt way to finish would be to animate from the current view state to the final one (this will interrupt the current, repeating animation).
- (IBAction)tap:(UITapGestureRecognizer *)sender
{
[UIView animateWithDuration:1
delay:0
options:UIViewAnimationOptionBeginFromCurrentState
animations:^{
self.label.alpha = 0;
} completion:^(BOOL finished){
[self presentNewView];
}];
}
You could put a pair of chained animation in a loop or call a function that holds the chained animation everytime until you encounter a user tap.
By Chained animation, I mean something like this (You can set the animation duration to suit your needs):
myLabel.alpha = 0.0;
[UIView animateWithDuration:1.0
delay:0.0
options: UIViewAnimationCurveEaseOut
animations:^{
myLabel.alpha = 1.0;
}
completion:^(BOOL finished){
[UIView animateWithDuration:1.0
delay:1.0
options: UIViewAnimationCurveEaseOut
animations:^{
myLabel.alpha = 0.0;
}
completion:^(BOOL finished){
NSLog(#"Done!");
}];
}];
The above code will first fade in your label and then fade it out. You can put that in a function and call it until you encounter user tap.
Create a CABasicAnimation and add it to your label:
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"opacity"];
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
animation.fromValue = #(1.0f);
animation.toValue = #(0.1f);
animation.repeatCount = INFINITY;
animation.duration = 0.75;
animation.autoreverses = YES;
[label.layer addAnimation:animation];
When you click on your button, just get a pointer to that label and remove all the animations:
[label.layer removeAllAnimations];
Try this it give you the ability to manage the animation repeat count if you replaced INFINITY with your repeat count
fadingLabel.alpha = 1.0;
[UIView beginAnimations:#"fadingLabel" context:nil];
[UIView setAnimationDuration:4.0];
[UIView setAnimationRepeatCount:INFINITY];
fadingLabel.alpha = 0.0;
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView commitAnimations];
Wayne Hartman's Answer in Swift 4
let animation = CABasicAnimation(keyPath: "opacity")
animation.fromValue = 1
animation.toValue = 0.1
animation.duration = 0.75
animation.repeatCount = .infinity
animation.autoreverses = true
label.layer.add(animation, forKey: nil)
and
label.layer.removeAllAnimations()

I want to flash an UIImageview on the iPad, how do I do that?

I want to let a UIImageView flash several times.
Currently I don't know how to do that.
Actual code:
-(void)arrowsAnimate{
[UIView animateWithDuration:1.0 animations:^{
arrow1.alpha = 1.0;
arrow2.alpha = 1.0;
arrow3.alpha = 1.0;
NSLog(#"alpha 1");
} completion:^(BOOL finished){
[self arrowsAnimate2];
}];
}
-(void)arrowsAnimate2{
[UIView animateWithDuration:1.0 animations:^{
arrow1.alpha = 0.0;
arrow2.alpha = 0.0;
arrow3.alpha = 0.0;
NSLog(#"alpha 0");
} completion:^(BOOL finished){;}];
}
later on I call it like this:
for (int i = 0;i < 10; i++){
[self arrowsAnimate]; }
This gives me 10x alpha 1, and then 10x alpha 0. In the middle we see only one animation.
Any suggestions?
Thanks.
There is a simpler way to achieve a flashing animation using only 1 animation block:
aview.alpha = 1.0f;
[UIView animateWithDuration:0.5f
delay:0.0f
options:UIViewAnimationOptionAutoreverse
animations:^ {
[UIView setAnimationRepeatCount:10.0f/2.0f];
aview.alpha = 0.0f;
} completion:^(BOOL finished) {
[aview removeFromSuperview];
}];
The trick is to use [UIView setAnimationRepeatCount:NTIMES/2]; *_inside_* your animation block.
No need for extra functions or extra loops.
Use
+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion
and pass the UIViewAnimationOptionRepeat and probably UIViewAnimationOptionAutoreverse in your options. You shouldn't need to provide a completion block and only perform the first animation.
Edit: here is some sample code for an image that fades in and out indefinitely.
[UIView animateWithDuration:1.0
delay:0.0
options:(UIViewAnimationOptionRepeat | UIViewAnimationOptionAutoreverse)
animations:^{
self.myImageView.alpha = 1.0;
}
completion:NULL];
Edit 2: I see you actually need to flash it 10 times only. I wasn't able to do that with blocks actually. When the completion block executed, the animation seemed to complete instantly the remaining 9 times. I was however able to do this with just the old-style animations quite easily.
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0];
[UIView setAnimationRepeatCount:10.0];
[UIView setAnimationRepeatAutoreverses:YES];
self.myImageView.alpha = 1.0;
[UIView commitAnimations];
Edit 3: I found a way to do this with blocks.
- (void)animate
{
if (self.animationCount < 10)
{
[UIView animateWithDuration:1.0
animations:^{
self.myImageView.alpha = 1.0;
}
completion:^(BOOL finished){
[self animateBack];
}];
}
}
- (void)animateBack
{
[UIView animateWithDuration:1.0
animations:^{
self.myImageView.alpha = 0.0;
}
completion:^(BOOL finished){
self.animationCount++;
[self animate];
}];
}
Above blinking may not work when your app go background and foreground at time of blinking.
Instead of these you can take a transparent image and your actual image and animate your ImageView
UIImageView *imageview=[UIImageView new];
imageview.animationDuration=1;
imageview.animationImages = your array of images;
[imageview startAnimating];
You need to wait for an animation to complete before launching a new one. You could chain your completion block in animate2 to go back to animate, and stop based on a counter property, implementing your loop in the animate/completion blocks instead of a separate loop.

Using Block Completion Handler in iOS 4 for animation

I would like to animate my subviews movement when rotating the device, changing the alpha to 0, move the view to the new position and reset the alpha to 1.
Using this code in didRotateFromInterfaceOrientation causes the view to flash and fade very quickly and then reappear. I would like to avoid this behaviour.
[UIView animateWithDuration:kAnimationDuration animations:^{
anObject.alpha = 0.0;
CGRect newFrame = anObject.frame;
newFrame.origin.x = newX;
newFrame.origin.y = newY;
newFrame.size.width = newWidth;
newFrame.size.height = newHeight;
anObject.frame = newFrame;
} completion:^ (BOOL finished){
if (finished) {
anObject.alpha = 1.0;
}
}];
Is there a way around this flashing?
Thanks
Maybe actually animate alpha on completition ? rather than flash it ? :)
[UIView animateWithDuration:kAnimationDuration animations:^{
anObject.alpha = 0.0;
CGRect newFrame = anObject.frame;
newFrame.origin.x = newX;
newFrame.origin.y = newY;
newFrame.size.width = newWidth;
newFrame.size.height = newHeight;
anObject.frame = newFrame;
} completion:^ (BOOL finished){
if (finished) {
[UIView animateWithDuration:kAnimationDuration
animations:^{
anObject.alpha = 1;}
}
}];
Cheers,
Krzysztof Zabłocki

how to stop animation after using beginAnimations?

i use the following code to do a string rolling, but how to stop the animation?
[UIView beginAnimations:#"ruucc" context:NULL];
[UIView setAnimationDuration:12.8f];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
[UIView setAnimationDelegate:self];
[UIView setAnimationRepeatAutoreverses:NO];
[UIView setAnimationRepeatCount:999999];
frame = label1.frame;
frame.origin.x = -12;
label1.frame = frame;
[UIView commitAnimations];
- (void)doAnimation
{
[UIView animateWithDuration:12.8f
delay: 0.0
options: UIViewAnimationCurveLinear
animations:^{
frame = label1.frame;
frame.origin.x = -12;
label1.frame = frame;
}
completion:^(BOOL finished){
if(keepAnimating) {
[self doAnimation];
}
}];
}
In header:
BOOL keepAnimating;
To start animation:
keepAnimating = YES;
[self doAnimation];
To stop animation:
keepAnimating = NO;
This solution uses the block-based animation methods on UIView. Concerning the old set of animation methods ( [UIView beginAnimations] etc ) the UIView class reference states:
Use of the methods in this section is discouraged in iOS 4 and later. Use the block-based animation methods instead.