Fade between text in a UILabel with delay - ios

I want to animate the text of a UILabel so that it shows one text for a couple of seconds and after that fades into a default text.
I'm currently using the following code:
-(void)tapOnBalance:(id)sender{
[UIView animateWithDuration:1.0 delay:0.0 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
cell.amountLabel.text = #"Hola!";
} completion:nil];
// Pause the function - act as a 'delay'
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:3]];
[UIView animateWithDuration:1.0 delay:0.0 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
cell.amountLabel.text = #"Hallo!";
} completion:nil];
}
This works, but the [NSRunLoop currentRunLoop] is pausing the entire app, blocking everything for 3 seconds.
How do I get rid of the block on the main thread and still get the same result?

A simple fade (not a cross-fade) can go like this:
// change a label's text after some delay by fading
// out, changing the text, then fading back in
- (void)fadeLabel:(UILabel *)label toText:(NSString *)toText completion:(void (^)(BOOL))completion {
[UIView animateWithDuration:0.2 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
label.alpha = 0.0;
} completion:^(BOOL finished) {
label.text = toText;
[UIView animateWithDuration:0.2 delay:0.0 options:UIViewAnimationOptionCurveEaseIn animations:^{
label.alpha = 1.0;
} completion:completion];
}];
}
// simpler signature that can be done on a perform
- (void)changeLabelText:(NSString *)toText {
[self fadeLabel:self.myLabel toText:toText completion:nil];
}
// set the label to something, then change it with a fade, then change it back
self.myLabel.text = #"text";
[self performSelector:#selector(changeLabelText:) withObject:#"hola!" afterDelay:4];
[self performSelector:#selector(changeLabelText:) withObject:#"text" afterDelay:8];
You could also nest the calls' completion blocks (and add a delay param) to do something similar without the performs. To do a cross-fade, apply a similar technique with two labels (that have the same frame) where one's alpha is zero and the other's alpha is one.

Related

Xcode5 - toggle button border color automatically

I new to IOS programming.
I want to toggle button border color automatically at start of apps to get user attention,
I have tried the below code, but only the final color is selected.
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDelay:0.0];
[UIView setAnimationDuration:3.0];
button.layer.borderWidth=2.5f;
button.layer.borderColor=[[UIColor blueColor]CGColor];
[UIView setAnimationDelay:3.0];
button.layer.borderColor=[[UIColor clearColor]CGColor];
[UIView setAnimationDelay:6.0];
button.layer.borderColor=[[UIColor redColor]CGColor];
[UIView commitAnimations];
}
What you're doing is an invalid way to chain animations. As a result, only the last changes are applied. Additionally, you should be using block based animations, which Apple has recommended since iOS 4. Should be something like this:
[UIView animateWithDuration:3.0 animations:^{
button.layer.borderWidth=2.5f;
button.layer.borderColor=[[UIColor blueColor]CGColor];
} completion:^(BOOL finished) {
[UIView animateWithDuration:3.0 animations:^{
button.layer.borderColor=[[UIColor clearColor]CGColor];
} completion:^(BOOL finished) {
[UIView animateWithDuration:3.0 animations:^{
button.layer.borderColor=[[UIColor redColor]CGColor];
}];
}];
}];
This answer is the same as 0x7fffffff's answer, except it uses block variables so it looks a little cleaner and hopefully makes more sense:
void (^animateToRed)(BOOL finished) = ^(BOOL finished) {
[UIView animateWithDuration:3.0 animations:^{
button.layer.borderColor=[[UIColor redColor]CGColor];
} completion: nil];
}
void (^animateToClear)(BOOL finished) = ^(BOOL finished) {
[UIView animateWithDuration:3.0 animations:^{
button.layer.borderColor=[[UIColor clearColor]CGColor];
} completion:animateToRed];
}
[UIView animateWithDuration:3.0 animations:^{
button.layer.borderWidth=2.5f;
button.layer.borderColor=[[UIColor blueColor]CGColor];
} completion:animateToClear];
UIView's animateWithDuration:animations:completion: method is the best way to animate changes over time.
It takes 3 arguments.
A duration as a CGFloat, which is a measure of the length of the animation in seconds.
An animation block, which tells what animations to perform.
A completion block, which allows you to execute code after the animation is complete.
This code snippet creates two completion blocks.
The animateToRed completion block handles the animating of the border to red. It's completion block is nil, at this point, we're done animating.
The animateToClear completion block handles the animating of the border to clear. It's completion block is the animateToRed which we just defined.
Finally, we call animateWithDuration, animating the border to blue, and passing the animateToClear block for the completion (which in turn calls the animateToRed block).
For an animation this simple and with no repeated animations, it may seem like slightly overkill to do it this way (though it is slightly more readable). However, with a more complicated series of animations, especially if there's any repetitiveness, creating block variables like this to use and pass quickly becomes quite helpful.

Fade animation inside for-loop

At least I would dream of this Animation Flow:
FadeIn to 50% with alpha:0.5 for 2 seconds
Then fadeIn to 100% with alpha:1 for 2 seconds
Then fade out to 0% with alpha:0 for 4 seconds
After the visible animation ends, the text for the label shall be changed and then the fade routine should start again as shown above.
I feel that this code here does not allow the step by step fade animation and the code commences too early without waiting to finish the Fade out section.
//A FOR Loop sets text for the _label then the Animation routine should start:
- (IBAction)startFade:(id)sender
{
[_label setAlpha:0.f];
[UIView animateWithDuration:2.f
delay:0.f
options:UIViewAnimationOptionCurveEaseIn
animations:^{
[_label setAlpha:1.f];
}
completion:^(BOOL finished) {
[UIView animateWithDuration:2.f
delay:0.f
options:UIViewAnimationOptionCurveEaseInOut
animations:^{
[_label setAlpha:0.f];
}
completion:nil];
}
];
}
// Somehow the code shall wait here for ending the visible (!!) animation in the UI
// to set a new text for _label with the FOR Loop
The whole issue took me some days to figure out so far. But I am stuck here with the problem to pause the code for a while as it does not automatically wait for the visual finishing of the animation which makes it difficult for me to go on.
I'm sure that is what you are really looking for; but it meets your description:
- (IBAction)startFade:(id)sender {
[_label setAlpha:0.f];
[UIView animateWithDuration:2.f delay:0.f options:UIViewAnimationOptionCurveLinear animations:^{
[_label setAlpha:0.5f];
} completion:^(BOOL finished) {
NSLog(#"1st step is done.");
[UIView animateWithDuration:2.f delay:0.f options:UIViewAnimationOptionCurveLinear animations:^{
[_label setAlpha:1.f];
} completion:^(BOOL finished) {
NSLog(#"2nd step is done.");
[UIView animateWithDuration:4.f delay:0.f options:UIViewAnimationOptionCurveLinear animations:^{
[_label setAlpha:0.f];
} completion:^(BOOL finished) {
NSLog(#"3rd step is done, text will be changed.");
// let me change the text
[_label setText:[[NSDate date] description]];
// let me start the animation over, welcome to my infinite loop.
[self startFade:nil];
}];
}];
}];
}

IOS: animation that don't call completion quickly

I have this code to simulate a multiple camera flash
[UIView animateWithDuration:0.1
delay:0.f
options:UIViewAnimationOptionAutoreverse
animations:^{
[UIView setAnimationRepeatCount:2];
flash.alpha=1.f;
}
completion:^(BOOL finished) {
flash.alpha = 0;
}];
flash is a white UIImageView (full screen) that starts with alpha = 0.
If you try to use this code, you will notice that at the end flash remains full white for a little time and it's not perfect for my effects, what can I do to solve this?
The problem with your code is you do autoreverse using the option UIViewAnimationOptionAutoreverse, while also specifying your own final state in the completion block.
Try this:
[UIView animateWithDuration:0.1f
delay:0
options:UIViewAnimationOptionAutoreverse
animations:^{
[UIView setAnimationRepeatCount:2];
flash.alpha=1.f;
}
completion:nil];

How do I have text fade in to a UILabel?

Right now I have an IBAction for a button which generates a random number with each number assigned to display text in a UILabel. Rather than just appear, I would like the text to fade in or any other interesting animation would be cool too. Does anyone know a simple way to make this happen?
Right now I just use
labelMain.text = #"my text";
I know this is a bit stale (11 months old), but I think it's worth mentioning an alternative to the other approaches posted, which I feel is a better solution.
Make use of the UIView transitionWithView:duration:options:animations:completion class-level method, like this:
NSTimeInterval duration = 0.5f;
[UIView transitionWithView:labelMain
duration:duration
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
labelMain.text = #"new value";
} completion:nil];
This will cross-fade from the previous value of labelMain.text to "new value".
This approach works on other view values as well, such as changing the image of a UIImageView, for instance.
See Apple's docs on the topic.
The following code will give you fading effect on your label.
- (IBAction)buttonClicked:(UIButton *)sender
{
labelMain.alpha = 0;
[UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationOptionCurveEaseIn
animations:^{ labelMain.alpha = 1;}
completion:nil];
}
label.text = #"old text";
[UIView animateWithDuration:0.4 animations:^{
label.alpha = 0.0f;
} completion:^(BOOL finished) {
label.text = #"next text";
[UIView animateWithDuration:0.4 animations:^{
label.alpha = 1.0f;
} completion:^(BOOL finished) {
NSLog(#"finished transition");
}];
}];
Try this:
[labelMain setAlpha:0];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.8];
[labelMain setAlpha:1];
[UIView commitAnimations];
Changing the duration is pretty simple - just adjust the value 0.8 in the code.
// fade out the current value
[UIView animateWithDuration:0.2
delay:0
options:0
animations:^{
labelMain.alpha = 0.0f;
}
completion:^(BOOL finished) {
// set the new value and fade in
labelMain.text = newValue;
[UIView animateWithDuration:0.2
delay:0
options:0
animations:^{
labelMain.alpha = 1.0f;
}
completion:nil];
}];
This will look like cross fade animation
[UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationOptionCurveEaseOut
animations:^{
labelMain.alpha = 0;
[UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationOptionCurveEaseIn
animations:^{ labelMain.alpha = 1;}
completion:nil];
} completion:nil];

animateWithDuration not recognised?

I'm trying to do a cross dissolve on three UILabels (display1, display2, display3), by using a block animation to fade out, change text and then fade them in one at a time. The code I'm using is:
[UIView animateWithDuration:1.0 delay: 1.0
animations:^{
display1.alpha = 0.0;
display2.alpha = 0.0;
display3.alpha = 0.0;
}
completion:^{
[display1 setText:[NSString stringWithFormat:#"%#",[engine getstring]]];
[display2 setText:[NSString stringWithFormat:#"%#",[engine getstring]]];
[display3 setText:[NSString stringWithFormat:#"%#",[engine getstring]]];
[UIView animateWithDuration:1.0 delay:1.0
animations:^{
display1.alpha = 1.0;
[UIView animateWithDuration:1.0 delay:1.0
animations:^{
display2.alpha = 1.0;
[UIView animateWithDuration:1.0
delay:1.0
animations:^{
display3.alpha = 1.0;
} completion:nil];
} completion:nil];
} completion:nil];
}];
I get the following warnings:
Method '+animateWithDuration:delay:animations:completion:' not found*
and
'UIView' may not respond to method '+animateWithDuration:delay:animations:completion:'
I'm using Xcode 4.0 with an iOS Build Target of 4.3.
You want to use
+ animateWithDuration:delay:options:animations:completion:
instead. Note the options: in the middle.

Resources