我尝试拖动视图,当拖动停止时,视图会滑到顶部并消失。我可以使用UIPanGestureRecognizer来拖动视图。但在那之后,我用动画让它滑出来。问题是在拖动之后,在视图移动之前总是有点打嗝......我四处搜索并且无法弄清楚如何解决这个问题。这是代码:
- (void)moveView2:(UIPanGestureRecognizer *)pan {
CGPoint delta = [pan translationInView:self.view];
CGPoint newCenter = CGPointMake(_view2.center.x, _view2.center.y + delta.y);
_view2.center = newCenter;
[pan setTranslation:CGPointZero inView:self.view];
if (pan.state == UIGestureRecognizerStateEnded) {
CGPoint velocity = [pan velocityInView:self.view];
NSLog(@"Velocity is %f, %f", velocity.x, velocity.y);
// Here is the delay
[UIView animateWithDuration:0.5 delay:0.0 usingSpringWithDamping:0.5f initialSpringVelocity:500 options:UIViewAnimationOptionCurveEaseInOut animations:^{
_view2.center = CGPointMake(_view2.center.x, -600);
} completion:nil];
}
#import "ViewController.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIButton *fbButton;
@property (weak, nonatomic) IBOutlet UIButton *twitterButton;
@property UIView *view1;
@property UIView *view2;
@property CGPoint startPoint;
@property CGPoint endPoint;
@property CGPoint originCenter;
@property double startTime;
@property double endTime;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
CGRect frame = [UIScreen mainScreen].bounds;
_view1 = [[UIView alloc] initWithFrame:frame];
_view1.backgroundColor = [UIColor redColor];
[self.view addSubview:_view1];
_view2 = [[UIView alloc] initWithFrame:frame];
_view2.backgroundColor = [UIColor greenColor];
[self.view addSubview:_view2];
UIPanGestureRecognizer *pan1 = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(moveView2:)];
[_view2 addGestureRecognizer:pan1];
/*
UISwipeGestureRecognizer *swipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeUpDown:)];
[swipe setDirection:UISwipeGestureRecognizerDirectionUp];
[_view2 addGestureRecognizer:swipe];
*/
}
/*
- (void)swipeUpDown:(UISwipeGestureRecognizer *)swipe {
if (swipe.direction == UISwipeGestureRecognizerDirectionUp) {
NSLog(@"Swipe up");
[UIView animateWithDuration:0.5 animations:^{
_view2.center = CGPointMake(_view2.center.x, -600);
}];
}
}*/
- (void)moveView2:(UIPanGestureRecognizer *)pan {
CGPoint bigViewDelta = [pan translationInView:self.view];
CGPoint newCenter = CGPointMake(_view2.center.x, _view2.center.y + bigViewDelta.y);
_view2.center = newCenter;
[pan setTranslation:CGPointZero inView:self.view];
if (pan.state == UIGestureRecognizerStateEnded) {
CGPoint velocityOfPan = [pan velocityInView:self.view];
CGFloat velocityOfPanAbsolute = sqrt(velocityOfPan.x * velocityOfPan.x + velocityOfPan.y * velocityOfPan.y);
// get simple points per second
CGPoint currentPoint = _view2.center;
CGPoint finalPoint = CGPointMake(_view2.center.x, -600);
CGFloat distance = sqrt((finalPoint.x - currentPoint.x) * (finalPoint.x - currentPoint.x) + (finalPoint.y - currentPoint.y) * (finalPoint.y - currentPoint.y));
// how far to travel
CGFloat duration = 0.5;
CGFloat animationVelocity = velocityOfPanAbsolute / (distance / duration);
[UIView animateWithDuration:duration delay:0.0 usingSpringWithDamping:1.0 initialSpringVelocity:animationVelocity options:0 animations:^{
_view2.center = CGPointMake(_view2.center.x, -600);
} completion:nil]; }
}
- (void)viewDidAppear:(BOOL)animated {
/*
[UIView transitionFromView:_view2 toView:_view1 duration:2 options:UIViewAnimationOptionCurveEaseInOut completion:^(BOOL finished) {
}];
*/
/*
// get the view that's currently showing
UIView *currentView = _view2;
// get the the underlying UIWindow, or the view containing the current view view
UIView *theWindow = [currentView superview];
// remove the current view and replace with myView1
[currentView removeFromSuperview];
//[theWindow addSubview:newView];
// set up an animation for the transition between the views
CATransition *animation = [CATransition animation];
[animation setDuration:0.5];
[animation setType:kCATransitionPush];
[animation setSubtype:kCATransitionFromLeft];
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[[theWindow layer] addAnimation:animation forKey:@"SwitchToView1"];
*/
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
答案 0 :(得分:6)
你的意思是动画发生之前的延迟吗?嗯,我没有看到任何导致这种情况的事情,但animateWithDuration
的参数非常非常好奇。
首先,UIViewAnimationOptionCurveEaseInOut
对我来说没有意义,因为过去常常说“慢慢开始,加快速度,慢慢停下来”#34 ;。标准动画很好,你不希望动画的开始过于刺耳。但是在这种情况下它没有意义,因为你可能希望它不要慢慢开始,而是要使用你最初提供的任何速度。如果我使用了option
,我会使用UIViewAnimationOptionCurveEaseOut
。即便这样也没有意义,因为usingSpringWithDamping
参数决定了这个动画结束时会发生什么。 (而且,最重要的是,你将它拖离屏幕,所以我不清楚为什么你还要关心退出曲线。)
其次,initialSpringVelocity
对我来说似乎也没有。正如此参数的文档所示:
初始弹簧速度。为了平滑地开始动画,请将此值与附件之前的视图速度相匹配。
值
1
对应于一秒内遍历的总动画距离。例如,如果总动画距离为200点,并且您希望动画的开始与100 pt / s的视图速度匹配,请使用值0.5
。
因此,500
表示您希望在一秒钟内将当前位置与最终位置之间的距离移动500倍。那太荒谬了。
我会尝试将初始速度与最终的手势速度相匹配。因此,计算手势的绝对速度,并将其除以要行进的距离除以动画的持续时间。
第三,如果您将其拖离屏幕,我不确定您为什么要使用usingSpringWithDamping
0.5
。那很有弹性。为什么你希望它能够在你停止使用屏幕时使用,而你却无法看到它?让我感到震惊的是,任何小于1.0
的值都会冒着视图在一个或多个初始弹簧中弹回可见屏幕的可能性。如果在屏幕上设置动画,我将不会使用1.0
之外的任何内容。
把它们全部拉到一起,我得到类似的东西:
CGPoint velocityOfPan = [pan velocityInView:self.view];
CGFloat velocityOfPanAbsolute = hypof(velocityOfPan.x, velocityOfPan.y); // get simple points per second
CGPoint currentPoint = _view2.center.x;
CGPoint finalPoint = CGPointMake(_view2.center.x, -600);
CGFloat distance = hypof(finalPoint.x - currentPoint.x, finalPoint.y - currentPoint.y); // how far to travel
CGFloat duration = 0.5;
CGFloat animationVelocity = velocityOfPanAbsolute / (distance / duration);
[UIView animateWithDuration:duration delay:0.0 usingSpringWithDamping:1.0 initialSpringVelocity:animationVelocity options:0 animations:^{
_view2.center = CGPointMake(_view2.center.x, -600);
} completion:nil];
说完所有这些之后,虽然可能animateWithDuration
因为"轻松放松"的组合而感到困惑。而戏剧性的initialSpringVelocity
,我实际上并不明白为什么会导致"打嗝"。
在这个动画之后你是否正在做任何其他事情?任何可能阻塞主队列的东西?
你的意思是在手势首次被识别之前有点延迟吗?是的,这是平移手势识别器的一个功能。 (我认为它试图确定它是否真的是一个泛声与长按vs等)。
您可以使用UILongPressGestureRecognizee
minimumPressDuration
为零来解决此问题(尽管您必须自己计算translationInView
)。