简体   繁体   中英

Animation without delay (UIView animateWithDuration delay)

We need to show 10 images sequentially with a certain time interval (default images are in hidden = yes and have a tag from 1111 to 1120). The result of the code is the appearance of images all at once, without delay. Animation is made a separate function. What could be the problem? I am using xcode 8.2.1

-(void)doski:(NSInteger)i
    {
    [UIView animateWithDuration:1.0
                            delay:5.0
                            options:UIViewAnimationOptionAutoreverse | UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowUserInteraction
                         animations:^(void) {
                         }
                         completion:^(BOOL finished) {
                             [self.view viewWithTag:(i+1110)].hidden=NO;
                             NSInteger i2=i;
                             i2++;
                             if(i2<11)
                             [self doski:i2];
                             }];
    }
    ...........
    //function call
    [self doski:1];

When you use this option, the situation has not changed:

   -(void)doski:(NSInteger)i
        {
    [UIView animateWithDuration:1.0 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut
                     animations:^(void) {
                     }
                     completion:^(BOOL finished){
                         [UIView animateWithDuration:2.0 delay:1.0 options:
                          UIViewAnimationOptionCurveEaseIn animations:^{
                              [self.view viewWithTag:(i+1110)].hidden=NO;
                          } completion:^ (BOOL completed) {NSInteger i2=i;
                              i2++;
                              if(i2<18)
                              [self doski:i2];}];
                     }];
}

Thank you.

I think the reason for the images appearing immediately is the fact that your animation blocks are empty. With an empty animation block, the completion block will be called immediately (there is nothing to animate so we might as well be done).

To fix your code, you could try something like this before your call to animateWithDuration...

UIView *viewToAnimate = [self.view viewWithTag:(i+1110)]
viewToAnimate.alpha = 0
viewToAnimate.hidden = NO

Then set the alpha to 1 inside the animation block like so:

viewToAnimate.alpha = 1

Here is a complete example illustrating the problem with an empty animation block. You can copy and paste it into a playground. It's Swift though, not Objective-C

import UIKit
import PlaygroundSupport

class MyView : UIView {

    override init(frame: CGRect) {
        super.init(frame: frame)
        self.setup()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    private func setup() {
        let view = UIView(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
        view.backgroundColor = UIColor.red
        self.addSubview(view)

        UIView.animate(withDuration: 2, delay: 1, options: [], animations: {
            // commenting out the following line will
            // trigger the completion block immediately
            view.frame = CGRect(x: 300, y: 300, width: 50, height: 50)
        }, completion: { finished in
            print("done")
        })
    }

}

let view = MyView(frame: CGRect(x: 0, y: 0, width: 400, height: 400))
view.backgroundColor = UIColor.black
PlaygroundPage.current.liveView = view

You have multiple problems with your code.

You can't animate the hidden property of a view. The hidden property is not animatable. Instead, you need to set the alpha value to 0 and animate it to 1.0. That will cause the view to fade in, which is, I assume, what you want.

Both of your code blocks does not do anything inside the animation block. That's wrong. Inside the animations block, you need to change one or more animatable properties of the view that you want to animate.

If you want the views to show up one at a time then you should call animateWithDuration:delay:options:animations:completion: with a delay value of 0 for the first animation, and a delay of the duration of the first animation for the second one, etc. That way the first animation will begin immediately, the second animation will start when the first one finishes, and so on.

Your code might look something like this:

NSTimeInterval duration = 0.25;
for (index = 0; x < 10; x++) {
   UIView *viewToAnimate = arrayOfViewsToAnimate[index];

   //For each view, set it's hidden property to false 
   //and it's alpha to zero
   viewToAninimate.hidden = false;
   viewToAnimate.alpha = 0.0;
   [UIView animateWithDuration:duration
     delay: duration * index
     options: 0
     animations: ^ {
       //inside the animation block, set the alpha to 1.0
       viewToAnimate.alpha = 1.0;
     }
     completion: nil
   ];
}

That code assumes that you have created an array arrayOfViewsToAnimate that contains the views that you want to animate. You could also assign tags to the views and find each view using that tag in your for loop. In any case you will need to adapt the code above to your needs, not just copy/paste it into your program.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM