如何动画使用AutoLayout向上滑动UIView? [英] How to animate slide up UIView with AutoLayout?

查看:138
本文介绍了如何动画使用AutoLayout向上滑动UIView?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这就是我想要实现的目标:

this is what I like to achieve:

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

I want to perform a slide up animation where a user can slide a UIView2 up, and the UIView2 will stop half-way on the screen.

我知道如何通过像这样的UIButton动作以模态方式呈现UIViewControler:

I know how to present a UIViewControler modally via a UIButton action like so:

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

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

I also know you need this type of code for animations:

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

}];

但是,我不知道如何使用UIViews来实现这一点,特别是因为我使用AutoLayout作为我的项目和我使用约束来轻松支持多种屏幕尺寸。

However, I'm not sure how to achieve this with UIViews, especially since I use AutoLayout for my project and I use constraints to easily support multiple screen sizes.

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

How can I achieve this without breaking AutoLayout and the constraints I have set up?

谢谢

推荐答案

我在这种情况下通常做的是以下几点。

What I typically do in this situation is the following.

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

Add two constraints to your scene. One where UIView2 is aligned to the bottom of UIView1. The second, where it's aligned center of UIView1 (you'll want to ctrl+drag between the views to add the constraints appropriately). These constraints will initially conflict with one another, and that's fine.

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

Add IBOutlets to your view controller for the NSLayoutConstraints and assign the two constraints we've created to those IBOutlets.

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

Set the constraint priority on your initial condition to 999 (i.e. constraint priority on align to bottom should be 999). Set the constraint priority on the destination constraint to 998 (i.e. constraint priority on align center is 998). You'll now see that these constraints will no longer conflict. This is because the priority on one constraint overrides the other.

您可能会看到现在的位置。因此,当你想在约束之间动画 UIView2 时,交换优先级和动画!

You may see where this is headed now. So when you want to animate UIView2 between the constraints, swap the priorities and animate!

代码:

@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];
    }];
}

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

To enable panning and using that to initiate your animation add a Pan Gesture Recognizer to your view controller. Ctrl+drag from UIView2 to the Pan Gesture Recognizer and set it as a gestureRecognizer. Now when you drag on UIView2, you'll be able to receive pan events.

添加IBAction来处理pan:

Add an IBAction to handle the pan:

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

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

Ctrl+drag from the pan gesture recognizer to the view controller and set onPan: as the sent action.

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

sender is actually the pan gesture recognizer itself. So we'll be able to fill out this method to handle a pan and have UIView2 follow under the user's finger and then initiate the animation when they let go.

让我们开始填写代码:

- (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 ,你会看到如下输出:

If you run with this code, and drag your finger over UIView2, you'll see output like this:

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)。使用此信息,我们可以计算增量。

Notice that the values are constantly increasing. We'll want the incremental amount. Notice the state in the log. State (1) is drag start. State (2) is drag changed. State (3) is drag ended. Using this information, we can calculate the delta.

CGPoint 属性添加到视图控制器并将UIView2添加为还有一个IBOutlet:

Add a CGPoint property to your view controller and add UIView2 as an IBOutlet as well:

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

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

Finally, let's fill out the final form of our pan method:

- (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);
}

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

This should get you well on your way. You may want to look at tweaking the UIView animation on the constraints a bit based on the pan gesture's velocityInView: method, but that I'll leave as an exercise.

这篇关于如何动画使用AutoLayout向上滑动UIView?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆