如何动画使用AutoLayout向上滑动UIView?

时间:2014-12-22 18:33:56

标签: ios objective-c uiview

这是我想要实现的目标: enter image description here

我想执行一个向上滑动动画,用户可以向上滑动UIView2,UIView2将在屏幕中途停止。

我知道如何通过UIButton操作以模态方式呈现UIViewControler:

[self presentViewController:newController animated:NO completion:nil];

我也知道你需要这种类型的动画代码:

[UIView animateWithDuration:0.5f animations:^{
    [self.customView layoutIfNeeded];
} completion:^(BOOL finished) {

}];

但是,我不确定如何使用UIViews来实现这一点,特别是因为我将AutoLayout用于我的项目,并且我使用约束来轻松支持多种屏幕尺寸。

如何在不破坏AutoLayout和我设置的约束的情况下实现这一目标?

由于

1 个答案:

答案 0 :(得分:17)

在这种情况下我通常做的是以下内容。

为场景添加两个约束。一个UIView2UIView1底部对齐的地方。第二个,它与UIView1的中心对齐(您需要在视图之间按住Ctrl键并拖动以适当地添加约束)。这些约束最初会相互冲突,这很好。

IBOutlet添加到NSLayoutConstraints的视图控制器中,并将我们创建的两个约束分配给IBOutlet

将初始条件的约束优先级设置为999(即,对齐到底部的约束优先级应为999)。将目标约束的约束优先级设置为998(即,对齐中心的约束优先级为998)。您现在将看到这些约束将不再发生冲突。这是因为一个约束的优先级会覆盖另一个约束。

你可能会看到现在的发展方向。因此,当您想要在约束之间设置UIView2动画时,请交换优先级并设置动画!

代码:

@interface MyViewController ()
    @property (nonatomic, weak) IBOutlet NSLayoutConstraint* constraint0;
    @property (nonatomic, weak) IBOutlet NSLayoutConstraint* constraint1;
@end

- (void)someMethodWhereIWantToAnimate
{
    NSInteger temp = self.constraint0.priority;
    self.constraint0.priority = self.constraint1.priority;
    self.constraint1.priority = temp;

    [UIView animateWithDuration:0.3 animations:^{
        // Simplest is to use the main ViewController's view
        [self.view layoutIfNeeded];
    }];
}

要启用平移并使用它来启动动画,请向视图控制器添加平移手势识别器。按Ctrl +从UIView2拖动到Pan Gesture识别器并将其设置为gestureRecognizer。现在,当您拖动UIView2时,您将能够接收平移事件。

添加IBAction来处理平底锅:

- (IBAction)onPan:(id)sender
{
}

Ctrl +从平移手势识别器拖动到视图控制器,并将onPan:设置为已发送的操作。

sender实际上是平移手势识别器本身。因此,我们将能够填写此方法来处理平移并在用户的手指下跟随UIView2,然后在他们放手时启动动画。

让我们开始填写代码:

- (IBAction)onPan:(id)sender
{
    UIPanGestureRecognizer* recognizer = (UIPanGestureRecognizer*)sender;
    CGPoint translation = [recognizer translationInView:self.view];
    NSLog(@"State: (%d) Translation in view: (%f, %f)", recognizer.state, translation.x, translation.y);
}

如果您使用此代码运行,并将手指拖过UIView2,您将看到如下输出:

State: (1) Translation in view: (0.000000, -2.500000)
State: (2) Translation in view: (0.500000, -7.500000)
State: (2) Translation in view: (0.500000, -7.500000)
State: (2) Translation in view: (1.500000, -12.000000)
State: (2) Translation in view: (2.500000, -16.500000)
State: (2) Translation in view: (2.500000, -19.500000)
State: (2) Translation in view: (2.500000, -24.500000)
State: (2) Translation in view: (2.500000, -25.000000)
State: (2) Translation in view: (2.500000, -25.500000)
State: (2) Translation in view: (2.500000, -27.000000)
State: (2) Translation in view: (2.500000, -29.500000)
State: (2) Translation in view: (2.500000, -31.000000)
State: (2) Translation in view: (2.500000, -31.500000)
State: (3) Translation in view: (2.500000, -31.500000)

请注意,值会不断增加。我们想要增量。注意日志中的状态。状态(1)是拖动开始。状态(2)被拖动改变。拖拽状态(3)。使用此信息,我们可以计算增量。

向视图控制器添加CGPoint属性,并将UIView2添加为IBOutlet:

@property (nonatomic) CGPoint lastTranslation;
@property (nonatomic, weak) IBOutlet UIView* uiView2;

最后,让我们填写pan方法的最终形式:

- (IBAction)onPan:(id)sender
{
    UIPanGestureRecognizer* recognizer = (UIPanGestureRecognizer*)sender;
    CGPoint delta;
    switch(recognizer.state) {
        case UIGestureRecognizerStateBegan:
            // On state begin: delta is the translation. Store it in our member for later user.
            self.lastTranslation = delta = [recognizer translationInView:self.view];
            break;
        case UIGestureRecognizerStateChanged:
            // On state changed: calculate the difference between the translation and our
            // previous translation.
            delta = CGPointApplyAffineTransform([recognizer translationInView:self.view], CGAffineTransformMakeTranslation(-self.lastTranslation.x, -self.lastTranslation.y));
            self.lastTranslation = [recognizer translationInView:self.view];
            break;
        case UIGestureRecognizerStateEnded:
            // On state ended: Let's just do the constraint animation.
            [self someMethodWhereIWantToAnimate];
            break;
        default:
            break;
    }
    delta.x = 0; // Forces only vertical drag on the UIView2.
    self.uiView2.center = CGPointApplyAffineTransform(self.uiView2.center, CGAffineTransformMakeTranslation(delta.x, delta.y)); // Move our uiView2 based on the delta.
    NSLog(@"State: (%d) Translation in view: (%f, %f)", recognizer.state, delta.x, delta.y);
}

这样可以帮助你顺利完成任务。您可能希望根据平移手势来调整有关约束的UIView动画 velocityInView:方法,但我将作为练习留下。