11

我对自动布局很陌生,我对如何为视图设置动画感到困惑。

我读了很多,我知道你必须遵守约束,编辑它,并将它包装layoutIfNeeded在一个UIView动画块中。

但说到做到这一点,我有点迷失了。例如,如果有人可以向我解释这个动画是如何完成的,我会很高兴。

我认为它可能使用 a将前导空间UIPanGestureRecognizer更改为容器约束,但它可能使用 UIDynamics(用于右侧的反弹效果?)。constant

4

1 回答 1

16

UIPanGestureRecognizer好吧,使用+可以实现类似的行为[UIView animateWithDuration:animations:]。是的,您设置了前导空间约束并根据UIPanGestureRecognizer状态进行更改。请记住,您只需要设置最终约束(定义滑块的最终位置)。为您计算中间动画位置。对于滑块,我们有默认的左侧位置和激活的中间位置。

对于视图旋转,我们可以使用transform.UIView

IB中的自动布局约束:

IB中的自动布局约束

设置动画选项(UIViewAnimationOptionCurveEaseOut动画曲线)可以给人一种弹跳效果的感觉。UIPanGestureRecognizer代码(省略实例变量声明,因为它们的名称是不言自明的):

- (IBAction)onPan:(UIPanGestureRecognizer*)sender
{
    switch (sender.state) {
        case UIGestureRecognizerStateBegan:
            _startOffset = self.leadingSpace.constant;
            _maxOffset = self.slider.superview.frame.size.width
                - kHorizontalPadding
                - self.slider.frame.size.width;
            break;

        case UIGestureRecognizerStateChanged: {
            CGFloat offset = _startOffset + [sender translationInView:self.slider.superview].x;
            offset = MIN(offset, _maxOffset);

            self.leadingSpace.constant = offset;
            break;
        }

        case UIGestureRecognizerStateEnded: {
            CGFloat offset = _startOffset + [sender translationInView:sender.view.superview].x;
            UIColor *bgColor = [UIColor lightGrayColor];
            CGFloat rotation = 0;

            if (offset < _maxOffset) {
                offset = kHorizontalPadding;
            }
            else {
                offset = (_maxOffset + kHorizontalPadding)/2;
                bgColor = [UIColor redColor];
                rotation = M_PI_2;
            }

            self.leadingSpace.constant = offset;

            [UIView
             animateWithDuration:.5
             delay:0
             options:UIViewAnimationOptionCurveEaseOut
             animations:^{
                 [self.slider layoutIfNeeded];
                 self.slider.backgroundColor = bgColor;
                 self.slider.transform = CGAffineTransformMakeRotation(rotation);
             } completion:nil];

            break;
        }

        default:
            break;
    }
}

动画结果UIViewAnimationOptionCurveLinear(捕获模拟器):

动画结果

动画结果UIViewAnimationOptionCurveEaseOut(捕获模拟器):

动画结果

UIDynamics

使用 UIDynamics,事情变得更加复杂。好的起点是Ray Wenderlich UIKit Dynamics Tutorial

对于弹跳滑块,我们可以添加以下行为:

  • UIGravityBehavior它将滑块拉到起始位置。我们需要更改angle属性以将重力指向左侧。
  • UICollisionBehavior它定义了允许运动的左右边缘。translatesReferenceBoundsIntoBoundary如果我们将父视图视为边界,属性将很有用。此外,我们需要添加额外的边界以使用addBoundaryWithIdentifier:fromPoint:toPoint(或贝塞尔路径)在中间停止滑块。
  • UIDynamicItemBehavior更改elasticy和可能resistance的属性以分别配置反弹和加速。
  • 当用户释放滑块时,可能UIPushBehavior与识别velocityInView:器一起指定滑块速度
  • 可能UISnapBehavior作为替代品UIGravityBehavior
于 2014-02-15T21:04:33.687 回答