Question

i'd have to create some animated shapes in a uiview in my iphone app (with xcode), like these ones (circle , rectangle) The first one should be a circle increasing and decreasing its radius, from 0 to x and viceversa; the second one is a rectangle increasing its length from 0 to x, and viceversa. The shapes should be animated infinitely... until the user taps some button to stop the animations at some point. How can i achieve those particular draws and animations? What's the best way to achieve that? And how to stop them? Many thanks for any advice.

Was it helpful?

Solution

In my case I had to animate the movement of subviews of my UIView object and I accomplished it like this: break up the continuous animation into logical parts, animate a part and configure this animation to start another animation after it is done animating. Below you see my code as is (what it does is move subviews that are placed on a circle along that circle over a given angle).

- (void) animatePart: (NSString*) animationId finished: (NSNumber*) finished context: (void *) context
{
    // the context contains an NSNumber which is the angle remaining to turn the pieces
    CGFloat displacement = [trackSet currentDisplacementOnTrack:drag.trackIndex];
    NSMutableDictionary* contextDict = (NSMutableDictionary*) context;
    Move * move = (Move *) [contextDict objectForKey:ANIMCTX_MOVE];
    //NSNumber *direction = (NSNumber *) [contextDict objectForKey:ANIMCTX_DIRECTION];
    printf("> EVC animatePart: displ: %3.3f ",  displacement);
    if (FABS(displacement) < 0.1) {
        printf(", ending animation\n");
        // this is the last piece of animation
        [trackSet completeMoveOnTrack:move.trackRef];
        [self updatePiecesAnimatedFromModel];
        self.animationContext = nil;
    }
    else {
        CGFloat dir = displacement == 0 ? 0 : displacement / FABS(displacement);
        CGFloat delta = -ANIM_DELTASTATION * dir;
        printf(" EVC animatePart: delta: %3.3f\n", delta);
        CGFloat newDelta = FABS(delta) < FABS(displacement) ? delta : -displacement;
        [trackSet registerMoveOnTrack:drag.trackIndex by:newDelta];
        [UIView beginAnimations:animationId context:context];
        [UIView setAnimationDuration:0.1];
        [UIView setAnimationCurve:UIViewAnimationCurveLinear];
        [UIView setAnimationDelegate:self];
        [UIView setAnimationDidStopSelector:@selector(animatePart:finished:context:)];
        [self updatePiecesFromTrack:drag.trackIndex];
        [UIView commitAnimations];  

    }
    printf("< EVC animatePart\n");
}

As you can see, the UIView methods setDelegate: and animationDidStopSelector: are used to configure this animation to call a certain method after it's done animating. The selector passed here is that of this same method. This sounds like a recursive method (it even has a stop condition, just like recursive methods normally do), but it's not. So no worries about stack overflows ;-) For completeness, to kickstart this animation I use the method below (copied verbatim from my code).

- (void) animateMove: (Move *) move direction: (int) direction
{
    printf("> EVC animateMove: %d\n", direction * move.stations);
    NSMutableDictionary* dict = [NSMutableDictionary dictionaryWithObject:move forKey:ANIMCTX_MOVE];
    [dict setObject:[NSNumber numberWithInt: direction] forKey:ANIMCTX_DIRECTION];
    self.animationContext = dict;

    //[trackSet openMoveOnTrack:move.trackRef];
    // the move has already been carried out in the model, but is not yet reflected in the UI
    // we don't need to call trackSet's openMoveOnTrack and closeMoveOnTrack
    // for the animation we initially set the track's current displacement to that of the move
    // then in a series of animated steps we decrement that displacement gradually to zero,
    // while showing the intermediate results in the UI.
    CGFloat moveDisplacement = (CGFloat) (move.stations);
    [trackSet registerMoveOnTrack:move.trackRef by:moveDisplacement];
    [self animatePart:@"displacementAnimation" finished:[NSNumber numberWithInt:0] context:dict];
    printf("< EVC animateMove: \n");
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top