Autolayout,UIDynamics和动画

DCM*_*xxx 11 animation ios autolayout uikit-dynamics

我对自动布局很新,我对如何动画视图感到困惑.

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

但是当谈到这样做时,我有点失落.如果有人可以解释我这个动画是如何完成的,我会很高兴.

我认为它可能使用a UIPanGestureRecognizer来改变constant前导空间到容器约束,但它可能使用UIDynamics(对于右边的反弹效果?).

vok*_*lam 16

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

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

IB中的Autolayout约束:

IB中的Autolayout约束

设置动画选项(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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

动画结果

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

动画结果

UIDynamics

随着UIDynamics,事情变得更加复杂.好的起点是Ray Wenderlich UIKit Dynamics Tutorial.

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

  • UIGravityBehavior拉动滑块开始位置.我们需要将angle属性改为左侧的直接重力.
  • UICollisionBehavior它定义了允许运动的左右边缘.translatesReferenceBoundsIntoBoundary如果我们将父视图视为边界,则属性将非常有用.此外,我们需要添加额外的边界来使用addBoundaryWithIdentifier:fromPoint:toPoint(或bezier路径)在中间停止滑块.
  • UIDynamicItemBehavior更改elasticy和可能的resistance属性分别配置弹跳和加速.
  • 当用户释放滑块时,可能UIPushBehavior与识别器velocityInView:一起指定滑块速度
  • 可能UISnapBehavior作为替代品UIGravityBehavior