iOS Animation 学习(3)

View Animation Options

UIView的类方法 nimateWithDuration:animations: 和 animateWithDuration:animations:completion: 都是 animateWith- Duration:delay:options:animations:completion: 的缩减版,参数解析如下:

  • duration

    动画的播放时间:从开始到结束需要多长时间(以秒为单位)来运行。你也可以认为这是动画的速度。显然,如果两个视图被告知同样时间里移动至不同的距离,移动距离更远的速度更快。

  • delay

    动画开始之前的延时。默认在缩减版方法中时没有延时的。

  • options

    额外选项值结合起来的位掩码(使用按位或运算符)。

  • animations

    这个block包含属性变化的动画。

  • completion

    当动画结束时会执行这个block(可以是nil)。它有一个BOOL类型的参数来指定动画是否结束了。即使在上面的动画block中没有触发任何动画,这个block仍然会被传入YES参数来调用。你也可以在这个block中执行另外的动画。

下面是第三个参数选项的一些值,你可能会用到:

  • Animation curve

    动画曲线描述了动画变化的过程中,如何加快。 “ease”一词意味着动画在开始和结束时,由零速度和中心速度之间会有一个逐渐加速和逐渐减速的过程。最多选择一个值;如果你不指定任何值(或如果您使用的是简化形式,在没有选择:参数),默认使用UIViewAnimationOptionCurveEaseInOut。你可以选择下面的值之一:

    (1) UIViewAnimationOptionCurveEaseInOut

    (2) UIViewAnimationOptionCurveEaseIn

    (3)UIViewAnimationOptionCurveEaseOut

    (4)UIViewAnimationOptionCurveLinear (constant speed throughout)

  • UIViewAnimationOptionRepeat

    如果包括这个值,动画将无限重复。没有办法可以指定重复一定的数量;你要么永远重复要么不重复。

  • UIViewAnimationOptionAutoreverse

    如果包括的话,动画将从开始运行到终点(在给定持续时间),并且随后将从终点(在给定的持续时间也)运行到开始。按照文档的说法,你只能自动翻转,如果你还重复是不正确的;你可以使用一种或两种(或没有)。

    当使用UIViewAnimationOptionAutoreverse时,你可能会想要在动画终点做一些清理工作,以便在动画结束时,视图回到它的初始位置。为了明白我什么意思,可以看看下面的代码:

    NSUInteger opts = UIViewAnimationOptionAutoreverse; [UIView animateWithDuration:1 delay:0 options:opts animations:^{ CGPoint p = self.v.center; p.x += 100; self.v.center = p; } completion:nil];

这个视图会以动画形式向右移动100点,然后再移动会原来的位置 --然后就会跳到右边的100点位置。因为我们最后实际赋值给这个视图的center 的x 轴是向右100点,所以但动画结束时,这个“动画电影”被移除时,这个视图仍然在右边100点上。解决方法就是在 completion 处理block中把视图移回它原来的位置:

CGPoint pOrig = self.v.center;
NSUInteger opts = UIViewAnimationOptionAutoreverse;
[UIView animateWithDuration:1 delay:0 options:opts animations:^{
    CGPoint p = self.v.center;
    p.x += 100;
    self.v.center = p;
} completion:^(BOOL finished) {
    self.v.center = pOrig;
}];

下面是使用递归链的指定动画次数的方法:

- (void) animate: (int) count {
    CGPoint pOrig = self.v.center;
    NSUInteger opts = UIViewAnimationOptionAutoreverse;
    [UIView animateWithDuration:1 delay:0 options:opts animations:^{
        CGPoint p = self.v.center;
        p.x += 100;
        self.v.center = p;
    } completion:^(BOOL finished) {
        self.v.center = pOrig;
        if (count)
            [self animate:count-1];
    }]; 
}

但你传递一个2给这方法来调用,动画会执行3次,然后停止。但这种方式是很危险的,如果数值很大,很容易用完内存。

还有其他一些选项指定如果另一个动画已经在执行了该怎么做:

  • UIViewAnimationOptionBeginFromCurrentState

    如果这个动画修改的属性同样被一个已经执行的动画修改,这时,不会取消之前的动画,这个动画会使用展示层(presentation layer)来决定从哪里开始执行动画,如果可能,还会混合之前的动画。

  • UIViewAnimationOptionOverrideInheritedDuration

    防止从已经在执行的动画中继承动画的持续时间(默认是继承的)。

  • UIViewAnimationOptionOverrideInheritedCurve

    防止从已经在执行的动画中继承动画曲线(默认是继承的)。

为了说明 UIViewAnimationOptionBeginFromCurrentState ,考虑下面的代码:

[UIView animateWithDuration:1 animations:^{
    CGPoint p = self.v.center;
    p.x += 100;
    self.v.center = p;
}];
NSUInteger opts = 0;
[UIView animateWithDuration:1 delay:0 options:opts animations:^{
    CGPoint p = self.v.center;
    p.x = 0;
    self.v.center = p;
} completion:nil];

结果就是视图跳到右边的100点位置,然后向左边开始动画,移动。 这是因为第二个动画使第一个动画被取消了,向右是瞬间完成,而不是动画。但是,如果我们设定options为UIViewAnimationOptionBeginFromCurrentState,其结果是,该视图的动画从它的当前位置向左执行,并没有跳跃。

如果我们在第二个动画中把改变x变为改变y,会发生很有趣的事情。如果options为0,那么视图会跳到右边,然后向上移动。如果options为UIViewAnimationOptionBeginFromCurrentState,两个动画会结合起来,视图斜向移动(右上角)。

为了解析 UIViewAnimationOptionOverrideInheritedDuration,看下面的代码:

[UIView animateWithDuration:2 animations:^{
    CGPoint p = self.v.center;
    p.x += 100;
    self.v.center = p;
    NSUInteger opts = 0;
    [UIView animateWithDuration:0.5 delay:0 options:opts animations:^{
        self.v.backgroundColor = [UIColor blackColor];
    } completion:nil];
}];

如果options为0,那么颜色动画的时间跟x轴的动画时间一样,继承了x轴的动画时间。但是如果options为UIViewAnimationOptionOverrideInheritedDuration,每个动画都有自己的执行时间。

为了停止正在执行的动画,我们可以提供一个冲突的动画,设置视图的位置为最终的位置。

-(void) animate {
    CGPoint p = self.v.center;
    p.x += 100;
    self.pFinal = p;
    [UIView animateWithDuration:4 animations:^{
        self.v.center = p;
    }];
}
-(void) cancel {
    [UIView animateWithDuration:0 animations:^{
        CGPoint p = self.pFinal;
        p.x += 1;
        self.v.center = p;
    } completion:^(BOOL finished) {
        CGPoint p = self.pFinal;
        self.v.center = p;
    }]; 
}

为了停止一个重复执行的动画,我们可以:

-(void) animate {
    CGPoint p = self.v.center;
    self.pOrig = p;
    p.x += 100;
    NSUInteger opts = UIViewAnimationOptionAutoreverse |
    UIViewAnimationOptionRepeat;
    [UIView animateWithDuration:1 delay:0 options:opts animations:^{
        self.v.center = p;
    } completion: nil];
}
-(void) cancel {
    [UIView animateWithDuration:0 animations:^{
        self.v.center = self.pOrig;
    }];
}

如果你希望动画的停止不那么突然,可以:

-(void) cancel {
    NSUInteger opts = UIViewAnimationOptionBeginFromCurrentState;
    [UIView animateWithDuration:0.1 delay:0 options:opts animations:^{
        self.v.center = self.pOrig;
    } completion:nil];
}
原文地址:https://www.cnblogs.com/YungMing/p/4016519.html