【问题标题】:How to animate constraints one by one in IOS?如何在IOS中对约束逐一进行动画处理?
【发布时间】:2020-11-20 12:46:50
【问题描述】:

我有 6 个视图。我想一个一个地为约束设置动画,即,我只需要在第二个视图上的动画在第一个之后,然后在第二个第三个之后,依此类推。我已经在动画的完成处理程序中添加了代码,但它不起作用。所有约束的初始值在情节提要中设置为 300。我想把它一个一个改成0。现在,只有第一个动画在起作用。这就是我所做的。

layoutTopFirst.constant = 0.0;
    [UIView animateWithDuration:1.0 animations:^{
        [self.view layoutIfNeeded];
    } completion:^(BOOL finished) {
        self->layoutTopSecond.constant = 0.0;
        [UIView animateWithDuration:1.0 animations:^{
            [self.view layoutIfNeeded];
        } completion:^(BOOL finished) {
            self->layoutTopThird.constant = 0.0;
            [UIView animateWithDuration:1.0 animations:^{
                [self.view layoutIfNeeded];
            } completion:^(BOOL finished) {
                self->layoutTopFourth.constant = 0.0;
                [UIView animateWithDuration:1.0 animations:^{
                    [self.view layoutIfNeeded];
                } completion:^(BOOL finished) {
                    self->layoutTopFifth.constant = 0.0;
                    [UIView animateWithDuration:1.0 animations:^{
                        [self.view layoutIfNeeded];
                    } completion:^(BOOL finished) {
                        self->layoutTopSixth.constant = 0.0;
                        [UIView animateWithDuration:1.0 animations:^{
                            [self.view layoutIfNeeded];
                        } completion:^(BOOL finished) {
                            
                        }];
                    }];
                }];
            }];
        }];
    }];

如何一个接一个的做动画?

【问题讨论】:

  • “它不工作”以什么方式?一次全部制作动画吗?没有动画吗?只有第一个动画吗?请详细说明。
  • @Stonz2 我已经更新了这个问题。现在只有第一个动画了
  • 你能在每次完成时添加一个日志来看看发生了什么吗?请注意,这不完全是 Swift 主题,但没关系。
  • 这能回答你的问题吗? Change UIView constraints in chained animations

标签: ios objective-c swift nslayoutconstraint uiviewanimationtransition


【解决方案1】:

如果您显示所有代码(如何设置约束等)会有所帮助。

但是,这里有一个简单的例子。

它创建了 6 个标签,顶部约束为 100。点击“Do Anim”按钮将它们动画到顶部:0.0 ...再次点击以动画回 100:

#import "SequentialAnimViewController.h"

@interface SequentialAnimViewController () {
    NSMutableArray *views;
    NSMutableArray *topConstraints;
}
@end

@implementation SequentialAnimViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
    [button addTarget:self action:@selector(animViews) forControlEvents:UIControlEventTouchUpInside];
    [button setTitle:@"Do Anim" forState:UIControlStateNormal];
    button.backgroundColor = [UIColor colorWithWhite:0.9 alpha:1.0];
    button.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:button];
    
    [button.centerXAnchor constraintEqualToAnchor:[self.view centerXAnchor]].active = YES;
    [button.centerYAnchor constraintEqualToAnchor:[self.view centerYAnchor]].active = YES;
    [button.widthAnchor constraintEqualToConstant:200.0].active = YES;

    views = [NSMutableArray new];
    topConstraints = [NSMutableArray new];
    
    CGFloat x = 40.0;
    CGFloat w = 40.0;

    UILayoutGuide *g = [self.view safeAreaLayoutGuide];

    for (int i = 0; i < 6; i++) {
        UILabel *v = [UILabel new];
        v.backgroundColor = [UIColor blueColor];
        v.textColor = [UIColor yellowColor];
        v.textAlignment = NSTextAlignmentCenter;
        v.text = [NSString stringWithFormat:@"%i", i];
        v.translatesAutoresizingMaskIntoConstraints = NO;

        [self.view addSubview:v];
        [v.widthAnchor constraintEqualToConstant:w].active = YES;
        [v.heightAnchor constraintEqualToConstant:w].active = YES;
        [v.leadingAnchor constraintEqualToAnchor:g.leadingAnchor constant:x].active = YES;

        [topConstraints addObject:[v.topAnchor constraintEqualToAnchor:g.topAnchor constant:100.0]];
        [views addObject:v];

        x += w + 8;
    }
    
    [NSLayoutConstraint activateConstraints:topConstraints];
}

-(void)animViews {
    __block int i = 0;
    __block CGFloat newConstant = ((NSLayoutConstraint *)self->topConstraints[0]).constant == 0.0 ? 100.0 : 0.0;
    ((NSLayoutConstraint *)self->topConstraints[i++]).constant = newConstant;
    [UIView animateWithDuration:1.0 animations:^{
        [self.view layoutIfNeeded];
    } completion:^(BOOL finished) {
        ((NSLayoutConstraint *)self->topConstraints[i++]).constant = newConstant;
        [UIView animateWithDuration:1.0 animations:^{
            [self.view layoutIfNeeded];
        } completion:^(BOOL finished) {
            ((NSLayoutConstraint *)self->topConstraints[i++]).constant = newConstant;
            [UIView animateWithDuration:1.0 animations:^{
                [self.view layoutIfNeeded];
            } completion:^(BOOL finished) {
                ((NSLayoutConstraint *)self->topConstraints[i++]).constant = newConstant;
                [UIView animateWithDuration:1.0 animations:^{
                    [self.view layoutIfNeeded];
                } completion:^(BOOL finished) {
                    ((NSLayoutConstraint *)self->topConstraints[i++]).constant = newConstant;
                    [UIView animateWithDuration:1.0 animations:^{
                        [self.view layoutIfNeeded];
                    } completion:^(BOOL finished) {
                        ((NSLayoutConstraint *)self->topConstraints[i++]).constant = newConstant;
                        [UIView animateWithDuration:1.0 animations:^{
                            [self.view layoutIfNeeded];
                        } completion:^(BOOL finished) {
                            NSLog(@"All Done!");
                        }];
                    }];
                }];
            }];
        }];
    }];
}
@end

【讨论】:

    【解决方案2】:

    如果只有第一个动画,请确保

    • 您的其他五个约束引用都指向不同的垂直约束...例如,如果它们是 nil,您将看不到任何更改;
    • 他们都是isActive
    • 没有任何其他约束阻止更新的常量产生更改。

    对于它的价值,您可以考虑使用关键帧动画消除完成处理程序的塔,例如

    CGFloat relativeDuration = 1.0 / 6.0;
    
    [UIView animateKeyframesWithDuration:6 delay:0 options:kNilOptions animations:^{
        [UIView addKeyframeWithRelativeStartTime:0 relativeDuration:relativeDuration animations:^{
            self.topConstraint1.constant = 0;
            [self.view layoutIfNeeded];
        }];
    
        [UIView addKeyframeWithRelativeStartTime:1.0 * relativeDuration relativeDuration:relativeDuration animations:^{
            self.topConstraint2.constant = 0;
            [self.view layoutIfNeeded];
        }];
    
        [UIView addKeyframeWithRelativeStartTime:2.0 * relativeDuration relativeDuration:relativeDuration animations:^{
            self.topConstraint3.constant = 0;
            [self.view layoutIfNeeded];
        }];
    
        [UIView addKeyframeWithRelativeStartTime:3.0 * relativeDuration relativeDuration:relativeDuration animations:^{
            self.topConstraint4.constant = 0;
            [self.view layoutIfNeeded];
        }];
    
        [UIView addKeyframeWithRelativeStartTime:4.0 * relativeDuration relativeDuration:relativeDuration animations:^{
            self.topConstraint5.constant = 0;
            [self.view layoutIfNeeded];
        }];
    
        [UIView addKeyframeWithRelativeStartTime:5.0 * relativeDuration relativeDuration:relativeDuration animations:^{
            self.topConstraint6.constant = 0;
            [self.view layoutIfNeeded];
        }];
    } completion:nil];
    

    或者,更简单:

    NSArray <NSLayoutConstraint *> *constraints = @[self.topConstraint1, self.topConstraint2, self.topConstraint3, self.topConstraint4, self.topConstraint5, self.topConstraint6];
    
    CGFloat relativeDuration = 1.0 / (CGFloat) constraints.count;
    
    [UIView animateKeyframesWithDuration:totalDuration delay:0 options:kNilOptions animations:^{
        for (NSInteger i = 0; i < constraints.count; i++) {
            [UIView addKeyframeWithRelativeStartTime: ((CGFloat) i) * relativeDuration relativeDuration:relativeDuration animations:^{
                constraints[i].constant = 0;
                [self.view layoutIfNeeded];
            }];
        }
    } completion:nil];
    

    产生:

    【讨论】:

    • 我使用了关键帧动画并且效果很好。谢谢你:)
    猜你喜欢
    • 2019-08-31
    • 2019-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多