Animate UILabel text - ios

I'm new to iOS programming and i've got a question:
I want to make a kind of custom progress bar. I've created 2 UIViews, one above the other and animated the front UIView with this code:
[UIView animateWithDuration:1.5f delay:1.0f options:UIViewAnimationOptionCurveEaseInOut animations:^{
[barCima setFrame:CGRectMake(10, 300, value, 30)];
}
completion:nil];
But now, I would like to do something more. I want that while the width bar is growing, a UILabel appears with the current value. Example: I set de value to 300. While the animation is occurring, the UILabel is showing the progress until it reaches the 300 (1, 2, 3, 4, 5, 6, 7,...,300).

You need an NSTimer that fires every one second or so, and a counter. Whenever the NSTimer fires, the counter is incremented, and UILabel's text will be updated. It should look like this
int _counter; // An instance var
self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(timerFired) userInfo:nil repeats: YES];
// Be sure you call [self.timer invalidate] when you don't need it anymore
...
-(void)timerFired {
++ _counter;
self.label.text = [NSString stringWithFormat:#"%i", _counter];
}
Good luck thought I don't know what you use such a progress bar for!

Related

How to know if color "touch" another color

I'm trying to create something that if I have a UIView with background of yellow, and this view is moving on the screen, and somewhere placed another UIView with background of red. How can I know if the yellow color touch the red color? - which mean's that the first view touches the another view.
During the animation you will have to periodically check for intersection like #AMI289 has said. e.g.
- (void)animate {
// Use an NSTimer to check for intersection 10 times per second
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(checkForCollision) userInfo:nil repeats:YES];
[UIView animateWithDuration:5 animations:^{
// Do the animation
} completion:^(BOOL complete) {
// Tell timer to stop calling checkForCollision
[timer invalidate];
}];
}
- (void)checkForCollision {
if (CGRectIntersectsRect([viewOne.layer.presentationLayer frame], [viewTwo.layer.presentationLayer frame])) {
// Handle collision
}
}
It is important to get the presentation layer of the views that are being animated otherwise you will not detect incremental changes to the views' positions on the screen. You also need to invalidate the timer once you are done with it otherwise your checkForCollision method will continue to run indefinitely.

Animate UILabel value increment

I'm trying to increment a percentage view using the following code:
// Progress
[UIView animateWithDuration:5.0 animations:^{
for (float percent = 0.0; percent <= 0.86; percent+=0.01) {
NSLog(#"%f", percent);
self.circularProgress2.progress = percent;
}
}];
It doesn't animate, it goes straight to the final value. I know I can use NSTimer:
[NSTimer scheduledTimerWithTimeInterval:0.0001 target:self selector:#selector(onLableAnimateTick:) userInfo:nil repeats:YES];
And then change the value from inside the called method. But I have several bars on the same view, so I guess using the first option would be better for me.
If not possible, how would I duplicate the NSTimer behavior without having to create properties and methods for every progress bar?
All the code inside the animation-block will be executed which is your case is a for-loop. Consider the following case:
[UIView animateWithDuration:5.0 animations:^{
CGRect f = aView.frame;
f.origin.x = 20;
f.origin.x = 25;
f.origin.x = 40;
aView.frame = f;
}];
This will animate the view from it's current position to x = 40. Not animate to 20, then to 25, then to 40. The result of the block is that aViews frames origin.x should be 40, no matter what happened before that.
I'd say use a timer if you want to auto-increment the progress with a given interval. You can still animate the change of course (for example by overriding the setProgress-method on your Progress-view class and call an animation from there), but don't use an animation block to increment the model value (progress).

Trying to give UILabel a pulsing effect using NSTimer, but timers keep conflicting with one another

In order to show that a certain state is in progress, I'm "pulsing" the UILabel that corresponds to that state, fading it from white to dark grey repeatedly.
I'm accomplishing this with NSTimers as shown below:
- (void)pulseColorsOfLabel:(NSTimer *)timer {
_timer = timer;
UILabel *labelToPulse = timer.userInfo;
// Check pulseCycle to determine at what point in the color transition the label is
if (_pulseCycle == 0) {
[UIView transitionWithView:labelToPulse duration:0.75 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
labelToPulse.textColor = [UIColor darkGrayColor];
} completion:nil];
_pulseCycle = 1;
}
else if (_pulseCycle == 1) {
[UIView transitionWithView:labelToPulse duration:0.75 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
labelToPulse.textColor = [UIColor whiteColor];
} completion:nil];
_pulseCycle = 0;
}
}
And I use an NSTimer call to make that method fire every 0.75 seconds:
[NSTimer scheduledTimerWithTimeInterval:0.75 target:self selector:#selector(pulseColorsOfLabel:) userInfo:self.stateLabel repeats:YES];
And as the application goes through the various states, it marks the just completed state label green, invalidates the timer, and then changes the next state label to be pulsing (there's multiple states the app has to go through) with another NSTimer call. Basically a method is called as a delegate when the state changes, then the state is checked with a switch statement and the appropriate colors and pulsings are set.
Problem is, sometimes in the process of all the state labels turning green, some will disappear completely (as I assume they get stuck in the faded to white state against the white background) and sometimes they stay dark, or sometimes they pulse very sporadically.
I know this is an issue with the timers, as if I get less fancy and just make it change the state label to orange when in progress instead of pulsing, it works beautifully every time.
Any ideas what I could be doing here to make sure all the timer calls work well in conjunction with one another, and don't mess up the coloring of the labels?
I noticed in your code that _timer is assigned when the timer fires, which means that if the current timer hadn't fired at least once yet, you wouldn't be able to cancel it. Try invalidating and assigning the timer when you schedule it:
[_timer invalidate];
_timer = [NSTimer scheduledTimerWithTimeInterval:0.75 target:self selector:#selector(pulseColorsOfLabel:) userInfo:self.stateLabel repeats:YES];
If that doesn't work, some of your animations may be getting interrupted. Try removing the old animation before adding a new one:
UILabel *labelToPulse = timer.userInfo;
[labelToPulse.layer removeAllAnimations];

Showing every 5 seconds a new UIImageView with the help of NSTimer and UIView Animation?

I am trying to create a Calibration View! I have 12 calibration points as UIImageViews. Now I want to show every point for 5 seconds. So the whole calibration time is 1 minute. The Alpha of the ImageViews is set to 0.0! In the UI Animation I want to set the Alpha to 1.0 for one point after an other, for each point only for 5 seconds.
So far I did this (see the code)! But this animates me (fades in) after 5 seconds for 5 seconds all 12 Points at once!How can I solve this for one after another with a NSTimer and UI Animation? Thanks
-(id)init{
_calibrationViewArray = [[NSMutableArray alloc]init];
_calibrationPoint1 = [[UIImageView alloc]initWithFrame:(CGRectMake(115.5,113.0,25.0,25.0))];
_calibrationPoint1.backgroundColor = [UIColor redColor];
_calibrationPoint1.alpha = 0.0;
[self addSubview:_calibrationPoint1];
[_calibrationViewArray addObject:_calibrationPoint1];
[NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:#selector(onTimer) userInfo:nil repeats:YES];
}
-(void)onTimer{
for (int i = 0; i < [_calibrationViewArray count]; i++) {
UIImageView* currentCalibrationPoint = [_calibrationViewArray objectAtIndex:i];
[UIView beginAnimations:#"Calibration" context:nil];
[UIView setAnimationDuration:5.0];
// Make the animatable changes.
currentCalibrationPoint.alpha = 1.0;
// Commit the changes and perform the animation.
[UIView commitAnimations];
}
}
Declare a variable in your class to be:
int cont;
Initialize variable when is needed:
cont=0;
Change your code to this:
-(void)onTimer{
//Loop is not needed, with the timer and counter is enough
UIImageView* currentCalibrationPoint = [_calibrationViewArray objectAtIndex:cont];
[UIView beginAnimations:#"Calibration" context:nil];
[UIView setAnimationDuration:5.0];
// Make the animatable changes.
currentCalibrationPoint.alpha = 1.0;
// Commit the changes and perform the animation.
[UIView commitAnimations];
if(cont>0){
//Hide previous view (here you can make another animation, instead of changing alpha right away)
[_calibrationViewArray objectAtIndex:cont-1].alpha = 0.0;
}
cont++;//+1
}
In your onTimer method you shouldn't be looping over all of the image views, you should have a currentIndex or similar variable so you can just get the next image view and run an animation on it alone.
Do not use timer at all.
Use the:
[UIView animateWithDuration: animations: completion:]
method.
In the animation block fade one of the dots, then in completion block run the animation again.

How do I synchronize change in a UILabel text with a related animation?

I have an animation of a drinking glass filling up from empty to full, using CAKeyframeAnimation. The animation works perfectly fine.
I need to update a UILabel with the percentage corresponding to the fullness of the glass, i.e. it will read "0%" when the animation begins, and "100%" when it ends.
The keyframe animation runs for 5 seconds. I don't see a good way of updating this label. I can think of two options:
starting another thread and running a polling-type loop that updates the text at the cost of processing power.
break down the animation into 100 parts and use CABasicAnimation to update the text and then proceed with the next bit of glass animation.
Is there a better way to do this?
Thanks in advance
You can use either a NSTImer or dispatch_after() blocks to update the label at some scheduled interval:
// assume an ivar "NSTimer *myTimer" and "int count", initially 0
// fires 20 times, so update is 0.05
myTimer = NSTimer scheduledTimerWithTimeInterval:0.25 target:self selector:#selector(updateLabel:) userInfo:nil repeats:YES
- (void)updateLabel:(NSTimer *)timer
{
++count;
if(count >= 20) {
[timer invalidate];
}
CGFloat percent += 0.05;
myLabel.text = [NSString stringWithFormat:...
}

Resources