Display StopWatch Timer animated like the petrol pump meter using NSTimer
Asked Answered
C

5

3

I am new in iOS developement.When I press the stopwatch start button I want to display the timer like counter token effect.I have attached image for your reference.I have done to display secs and minutes but I dont know, How animate autoscroll effect? How can I do this?

When the counter is moving it shouldn't jump from one number to another number, instead it should move from one number to next number smoothly, just like the petrol pump meter. Thanks Default state

start 1

enter image description here

enter image description here

Caffrey answered 26/6, 2013 at 7:56 Comment(2)
You can use pickerview for smooth scrolling.Sublimation
@Caffrey check it outStander
S
1

You need to manually scroll tableView instead of scrollToRowAtIndexPath because this animation uses its own timer interval and its very difficult or we can say impossible to change its time interval.

So, I am Implementing an API for such kind of problems and made a demo app for you with smooth scrolling as you want.

You need to use an outer timer that fires every 1 second and an internal timer that will fire every 0.03 sec as my tableRow Height is 30 I calculated internal timer interval as :---

Move 30 pixels for 1 sec , then Move 1 pixel for 0.33 sec inside internal timer.

The Internal timer will invalidate and fire every 1 second as initialized within outer timer.

And internal timer will perform the movement of cell.

dial4 is a tableView

Have a look at my code.

#define rowHeight 30

-(void)startCounter
{
    outertimer=[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(snapCell) userInfo:nil repeats:YES];
}

-(void)stopCounter
{
    [outertimer invalidate];
}

-(void)snapCell
{
    NSLog(@"Initialize Internal timer %i",secLsb);
    secLsb++;

    if (secLsb==10) {
        [dial4 setContentOffset:CGPointMake(0, 0) animated:NO];
        secLsb=0;
         NSLog(@"dial content offset y is %f",dial4.contentOffset.y);
    }

    [internaltimer invalidate];
    internaltimer=[NSTimer scheduledTimerWithTimeInterval:0.03
                                     target:self
                                   selector:@selector(automaticScroll)
                                   userInfo:nil
                                    repeats:YES];
}

-(void)automaticScroll
{
    NSLog(@"val is & y ======== %f",dial4.contentOffset.y);

    [dial4 setContentOffset:CGPointMake(dial4.contentOffset.x,dial4.contentOffset.y+1) animated:NO];
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return rowHeight;
}

Have a look at Time Counter

Stander answered 5/7, 2013 at 12:10 Comment(1)
Wouldn't it work to use UIView animations to control contentOffset of your table view instead of implementing your own timer?Marshamarshal
M
2

I have done something like this before - this code is not necessarily clean, but it does the job.

You want to create twoUILabels in your .h file:

IBOutlet UILabel *figureLabel1;
IBOutlet UILabel *figureLabel2;

Then you want to create a BOOL so that we can tell which UILabel is visible to the user.

BOOL firstLabel;

So lets imagine that the initial label (showing the number 1) is figureLabel1 and the future UILabel to be displayed (showing the number 2) is figureLabel2. However when the counter adds one, then the figureLabel2 moves up and takes the figureLabel1's place. Then, while the figureLabel1 is hidden, it takes the place of figureLabel2 when figureLabel1 was visible.

See here:

    // Check what label is showing
    if (firstLabel == YES) {

    // Following code the hide and move the figureLabel1

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.5];
    [UIView setAnimationDelegate: self]; //or some other object that has necessary method
    [UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];

    // Slowing fade out the figureLabel1
    [figureLabel1 setAlpha:0];

    // Move the figureLabel1 up and out of the way
    [figureLabel1 setFrame:CGRectMake(20, 108, 287, 55)];

    [UIView commitAnimations];

    // Following code the show and move the figureLabel2

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.5];

    // Slowing fade in the figureLabel2
    [figureLabel2 setAlpha:1];

    // Move the figureLabel2 up and into position
    [figureLabel2 setFrame:CGRectMake(20, 141, 287, 55)];

    [UIView commitAnimations];

    // Update BOOL for next label
    firstLabel = NO;

} else {
    // Exactly the same but opposite

}

As I said, this is not pretty but it shows the basic concept. All the best!

Mercaptide answered 26/6, 2013 at 8:58 Comment(1)
Block based UIView animation has been recommended over beginAnimations / commitAnimations since ios4Braise
S
1

You need to manually scroll tableView instead of scrollToRowAtIndexPath because this animation uses its own timer interval and its very difficult or we can say impossible to change its time interval.

So, I am Implementing an API for such kind of problems and made a demo app for you with smooth scrolling as you want.

You need to use an outer timer that fires every 1 second and an internal timer that will fire every 0.03 sec as my tableRow Height is 30 I calculated internal timer interval as :---

Move 30 pixels for 1 sec , then Move 1 pixel for 0.33 sec inside internal timer.

The Internal timer will invalidate and fire every 1 second as initialized within outer timer.

And internal timer will perform the movement of cell.

dial4 is a tableView

Have a look at my code.

#define rowHeight 30

-(void)startCounter
{
    outertimer=[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(snapCell) userInfo:nil repeats:YES];
}

-(void)stopCounter
{
    [outertimer invalidate];
}

-(void)snapCell
{
    NSLog(@"Initialize Internal timer %i",secLsb);
    secLsb++;

    if (secLsb==10) {
        [dial4 setContentOffset:CGPointMake(0, 0) animated:NO];
        secLsb=0;
         NSLog(@"dial content offset y is %f",dial4.contentOffset.y);
    }

    [internaltimer invalidate];
    internaltimer=[NSTimer scheduledTimerWithTimeInterval:0.03
                                     target:self
                                   selector:@selector(automaticScroll)
                                   userInfo:nil
                                    repeats:YES];
}

-(void)automaticScroll
{
    NSLog(@"val is & y ======== %f",dial4.contentOffset.y);

    [dial4 setContentOffset:CGPointMake(dial4.contentOffset.x,dial4.contentOffset.y+1) animated:NO];
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return rowHeight;
}

Have a look at Time Counter

Stander answered 5/7, 2013 at 12:10 Comment(1)
Wouldn't it work to use UIView animations to control contentOffset of your table view instead of implementing your own timer?Marshamarshal
C
0

From image it can be assume that you are trying to get an effect like count-down timer. Have a look at countdown timer here. It may helps you somehow.

Enjoy Programming !!

Corenecoreopsis answered 1/7, 2013 at 9:9 Comment(0)
S
0

Refer both links for your output. It helps you

UIPickerView that looks like UIDatePicker but with seconds

and

How can I make my UIPickerView show labels after the selected value?

Thanks.

Sublimation answered 5/7, 2013 at 9:12 Comment(0)
T
0

Several good ideas here so far, but I'll add another.

First, be sure to set the container view (your blue rectangle) to clip children, using the Clip Subviews checkbox in Interface Builder.

Second, add a set of child views with images of each numeral for each digit to be presented (4 * 10 = 40 child views in your case). Use tags in IB so you can easily access each one. Set the initial bounds to just below your bottom margin.

Call UIView animateWithDuration. In the animations block, set the new digit view's frame to appear in the clipped parent view's bounds, and set the old digit view's frame to just above the container's bounds. Since both view's frame changes are animated in the same block, this will create the effect of the new digit sliding up into place as the old digit slides out the top.

In the completion block, set the old digit's frame back to the original position below the container view.

With this approach, you can play with the duration and the timing curves, so that you cam emulate the pause that occurs with each digit fully displayed between transitions.

A similar approach can also be used with CALayer, or with sprites, but UIViews are lightweight, perform well, and easiest to assemble in Interface Builder.

Texture answered 6/7, 2013 at 5:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.