这是我想要实现的目标:
我想执行一个向上滑动动画,用户可以向上滑动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和我设置的约束的情况下实现这一目标?
由于
答案 0 :(得分:17)
在这种情况下我通常做的是以下内容。
为场景添加两个约束。一个UIView2
与UIView1
底部对齐的地方。第二个,它与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:
方法,但我将作为练习留下。