我通常在这种情况下会采取以下步骤。
给你的场景添加两个约束条件。一个是让 UIView2
对齐到 UIView1
的底部,另一个是让它对齐到 UIView1
的中心(你需要在视图之间进行 ctrl+drag 操作以适当添加约束条件)。这些约束条件最初会相互冲突,但这没关系。
为你的视图控制器添加 NSLayoutConstraints
的 IBOutlet
,并将我们创建的两个约束条件分配给这些 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:^{
[self.view layoutIfNeeded];
}];
}
为了启用平移并使用它来启动您的动画,请向您的视图控制器添加一个Pan Gesture Recognizer。从UIView2到Pan Gesture Recognizer进行Ctrl+拖动,并将其设置为gestureRecognizer。现在,当您在UIView2上拖动时,您将能够接收平移事件。
添加一个IBAction来处理平移:
- (IBAction)onPan:(id)sender
{
}
从平移手势识别器(Ctrl+drag)拖动到视图控制器,并设置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:
self.lastTranslation = delta = [recognizer translationInView:self.view];
break;
case UIGestureRecognizerStateChanged:
delta = CGPointApplyAffineTransform([recognizer translationInView:self.view], CGAffineTransformMakeTranslation(-self.lastTranslation.x, -self.lastTranslation.y));
self.lastTranslation = [recognizer translationInView:self.view];
break;
case UIGestureRecognizerStateEnded:
[self someMethodWhereIWantToAnimate];
break;
default:
break;
}
delta.x = 0;
self.uiView2.center = CGPointApplyAffineTransform(self.uiView2.center, CGAffineTransformMakeTranslation(delta.x, delta.y));
NSLog(@"State: (%d) Translation in view: (%f, %f)", recognizer.state, delta.x, delta.y);
}
这应该可以帮助你迈出重要的一步。根据手势的 velocityInView:
方法,您可能想微调约束上的UIView动画,但我会将其留作练习。
someMethodWhereIWantToAnimate
方法,从而使你的视图进行动画。我会再添加一个滑动手势识别器来处理向下滑动的情况。我还会将其中一个设置为禁用状态,并在手势执行时切换启用状态。如果你需要更详细的示例,请告诉我,我会尽量在明天更新我的答案。 - Sandy Chapman