user2014474
user2014474

Reputation: 1117

How to create an animation block IOS

I have four UIbuttons and I have to change their x origin. By now I am using this method:

[UIView animateWithDuration:1.0
                          delay:1.0
                        options: UIViewAnimationCurveEaseInOut
                     animations:^{

                     self.Button1.frame = CGRectMake(-120, self.Button1.frame.origin.y, self.Button1.frame.size.width, self.Button1.frame.size.height);

                     }
                     completion:^(BOOL finished){

                        [UIView animateWithDuration:1.0
                          delay:1.0
                        options: UIViewAnimationCurveEaseInOut
                     animations:^{

                     self.Button1.frame = CGRectMake(-140, self.Button1.frame.origin.y, self.Button1.frame.size.width, self.Button2.frame.size.height);

                     }
                     completion:^(BOOL finished){


                     }];
                     }];

I am putting one animation in the completition section of the next. But I have 4/5 buttons. I can't do this so many times. Is there a way to do an animation on an object, and after a delay of 0.5 seconds do it on the next?

EDIT:

I tried to use this:

typedef void (^AnimationBlock)();

AnimationBlock firstAnimation = ^{ self.Button1.frame = CGRectMake(-120, self.Button1.frame.origin.y, self.Button1.frame.size.width, self.Button1.frame.size.height); };

AnimationBlock secondAnimation = ^{ self.Button4.frame = CGRectMake(-120, self.Button4.frame.origin.y, self.Button4.frame.size.width, self.Button4.frame.size.height);};

[UIView animateWithDuration:2 animations:firstAnimation completion:^(BOOL finished) {
    [UIView animateWithDuration:2 animations:secondAnimation];
}];

but there is no possibility to set the time between the two animations.

Upvotes: 3

Views: 230

Answers (2)

LombaX
LombaX

Reputation: 17364

Do something like this (in this example I'm moving the same UIButton in all animations because I tried first on XCode, but you can change the content of the animation blocks as you prefer)

typedef void (^AnimationBlock)();

// declare two example animations
AnimationBlock firstAnimation = ^{
    CGRect firstFrame = self.aButton.frame;
    firstFrame.origin.x = firstFrame.origin.x - 20;
    self.aButton.frame = firstFrame;
};

AnimationBlock secondAnimation = ^{
    CGRect firstFrame = self.aButton.frame;
    firstFrame.origin.x = firstFrame.origin.x - 20;
    self.aButton.frame = firstFrame;
};

// starting point, create an array of animations
NSArray *animations = @[firstAnimation, secondAnimation];

// first animation starts immediately
double delayInSeconds = 0.0;
for (AnimationBlock animation in animations) {

    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){

        [UIView animateWithDuration:0.5f animations:[animation copy]];
    });

    // first animation starts immediately, then increase the dispatch_after timer of 0.5 sec at each loop
    delayInSeconds = delayInSeconds + 0.5f;
}

Essentially:

  • declare your animation blocks, how many as you want
  • put it inside an array
  • for loop: at each loop, add an animation to the dispatch after queue. At each loop, increase the delay. So, at the end of the loop, you will have X animation (as many as the count of the animations array) all starting at start at 0.5 sec delay from the previous one

Upvotes: 1

Craig Siemens
Craig Siemens

Reputation: 13276

What I would do is just take the code you have and make it more generic. Then you can simply animate any button with any delay.

- (void)animateButton:(UIButton *)button toRect:(CGRect)rect1 thenToRect:(CGRect)rect2 withDelay:(CGFloat)delay
{
    [UIView animateWithDuration:1.0
                          delay:delay
                        options:UIViewAnimationCurveEaseInOut
                     animations:^{
                         button.frame = rect1;
                     }
                     completion:^(BOOL finished){
                        [UIView animateWithDuration:1.0
                                              delay:delay
                                            options:UIViewAnimationCurveEaseInOut
                                         animations:^{
                                             button.frame = rect2;
                                         }
                                         completion:nil];
                     }];
}

Then you use it like this (I simplified the rect creation code to make it cleaner)

[self animateButton:self.button1
             toRect:CGRectOffset(self.button1.frame, -120 - self.button1.frame.origin.x)
         thenToRect:CGRectOffset(self.button1.frame, -140 - self.button1.frame.origin.x)
              delay:0.5f];

Upvotes: 2

Related Questions