UIPanGestureRecognizer状态结束后动画中的小嗝

时间:2014-10-29 05:41:49

标签: ios animation uipangesturerecognizer

我尝试拖动视图,当拖动停止时,视图会滑到顶部并消失。我可以使用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

1 个答案:

答案 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)。