2012-11-17 29 views
2

我需要的是当UIImageView从屏幕上拖出时,它会在放开时弹回。我在左边和上边工作,这是我正在做的事情。将UIImageView弹回屏幕时退回

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {   

     if (!CGRectContainsPoint(self.view.frame, imageView.frame.origin)){ 

      CGFloat newX = 0.0f; 
      CGFloat newY = 0.0f; 

      // If off screen upper and left 

      if (imageView.frame.origin.x < 0.0f){ 
       CGFloat negX = imageView.frame.origin.x * -1; 
       newX = negX; 
      }else{ 
       newX = imageView.frame.origin.x; 
      } 

      if (imageView.frame.origin.y < 0.0f){ 
       CGFloat negY = imageView.frame.origin.y * -1; 
       newY = negY; 
      }else{ 
       newY = imageView.frame.origin.y; 
      } 


      CGRect newPoint = CGRectMake(newX, newY, imageView.frame.size.width, imageView.frame.size.height); 

      [UIView beginAnimations:@"BounceAnimations" context:nil]; 
      [UIView setAnimationDuration:.5]; 
      [letterOutOfBounds play]; 
      [imageView setFrame:newPoint]; 

      [UIView commitAnimations]; 

     } 
    } 
} 

所以,我想实现右侧和底侧的相同的事情。但我一直坚持这一点。有任何想法吗?

回答

6

下面是怎么样的?

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { 

    UIImageView *imageView = nil; 

    BOOL moved = NO; 
    CGRect newPoint = imageView.frame; 

    // If off screen left 

    if (newPoint.origin.x < 0.0f){ 
     newPoint.origin.x *= -1.0; 
     moved = YES; 
    } 

    // if off screen up 

    if (newPoint.origin.y < 0.0f){ 
     newPoint.origin.y *= -1.0; 
     moved = YES; 
    } 

    // if off screen right 

    CGFloat howFarOffRight = (newPoint.origin.x + newPoint.size.width) - imageView.superview.frame.size.width; 
    if (howFarOffRight > 0.0) 
    { 
     newPoint.origin.x -= howFarOffRight * 2; 
     moved = YES; 
    } 

    // if off screen bottom 

    CGFloat howFarOffBottom = (newPoint.origin.y + newPoint.size.height) - imageView.superview.frame.size.height; 
    if (howFarOffBottom > 0.0) 
    { 
     newPoint.origin.y -= howFarOffBottom * 2; 
     moved = YES; 
    } 

    if (moved) 
    { 
     [UIView beginAnimations:@"BounceAnimations" context:nil]; 
     [UIView setAnimationDuration:.5]; 
     [letterOutOfBounds play]; 
     [imageView setFrame:newPoint]; 

     [UIView commitAnimations]; 
    } 
} 

当我读到你的代码,逻辑“如果关闭左侧,回到将其移动到相同的距离是关闭屏幕的看法。”说实话,这对我来说并不合适(为什么当反弹时,坐标取决于屏幕有多远),但我试图在“屏幕右侧”对其进行兑现,并且“屏幕底部”逻辑。显然,我的逻辑是使用superviewimageView来确定包含视图的宽度,但如果不合适,请将其替换为任何内容。

编辑:

我亲自做这个东西与手势识别,如:

UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)]; 
[self.imageView addGestureRecognizer:pan]; 
self.imageView.userInteractionEnabled = YES; 

因此,手势识别动画移动图像后面将是:

- (void)handlePan:(UIPanGestureRecognizer *)gesture 
{ 
    static CGRect originalFrame; // you could make this an ivar if you want, but just for demonstration purposes 

    if (gesture.state == UIGestureRecognizerStateBegan) 
    { 
     originalFrame = self.imageView.frame; 
    } 
    else if (gesture.state == UIGestureRecognizerStateChanged) 
    { 
     CGPoint translate = [gesture translationInView:gesture.view]; 

     CGRect newFrame = originalFrame; 

     newFrame.origin.x += translate.x; 
     newFrame.origin.y += translate.y; 

     gesture.view.frame = newFrame; 
    } 
    else if (gesture.state == UIGestureRecognizerStateEnded || gesture.state == UIGestureRecognizerStateCancelled) 
    { 
     CGRect newFrame = gesture.view.frame; 

     newFrame.origin.x = fmaxf(newFrame.origin.x, 0.0); 
     newFrame.origin.x = fminf(newFrame.origin.x, gesture.view.superview.bounds.size.width - newFrame.size.width); 

     newFrame.origin.y = fmaxf(newFrame.origin.y, 0.0); 
     newFrame.origin.y = fminf(newFrame.origin.y, gesture.view.superview.bounds.size.height - newFrame.size.height); 

     // animate how ever you want ... I generally just do animateWithDuration 

     [UIView animateWithDuration:0.5 animations:^{ 
      gesture.view.frame = newFrame; 
     }]; 
    } 
} 

或者,如果你想要一个手势识别器,只是防止首先从屏幕上拖出图像,它就会LD是:

- (void)handlePan:(UIPanGestureRecognizer *)gesture 
{ 
    static CGRect originalFrame; 

    if (gesture.state == UIGestureRecognizerStateBegan) 
    { 
     originalFrame = self.imageView.frame; 
    } 
    else if (gesture.state == UIGestureRecognizerStateChanged) 
    { 
     CGPoint translate = [gesture translationInView:gesture.view]; 

     CGRect newFrame = originalFrame; 

     newFrame.origin.x += translate.x; 
     newFrame.origin.x = fmaxf(newFrame.origin.x, 0.0); 
     newFrame.origin.x = fminf(newFrame.origin.x, gesture.view.superview.bounds.size.width - newFrame.size.width); 

     newFrame.origin.y += translate.y; 
     newFrame.origin.y = fmaxf(newFrame.origin.y, 0.0); 
     newFrame.origin.y = fminf(newFrame.origin.y, gesture.view.superview.bounds.size.height - newFrame.size.height); 

     gesture.view.frame = newFrame; 
    } 
} 

顺便说一句,在搭载iOS 7,您可以通过使用新的animationWithDurationusingSpringWithDampeninginitialSpringVelocity参数给图像视图的动画回到它原来的位置一点点反弹力:

[UIView animateWithDuration:1.0 
         delay:0.0 
    usingSpringWithDamping:0.3 
     initialSpringVelocity:0.1 
        options:0 
       animations:^{ 
        // set the new `frame` (or update the constraint constant values that 
        // will dictate the `frame` and call `layoutViewsIfNeeded`) 
       } 
       completion:nil]; 

或者,在iOS7,你也可以使用UIKit的动态添加UISnapBehavior

self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; 
self.animator.delegate = self; 

UISnapBehavior *snap = [[UISnapBehavior alloc] initWithItem:self.viewToAnimate snapToPoint:CGPointMake(self.viewToAnimate.center.x, self.view.frame.size.height - 50)]; 

// optionally, you can control how much bouncing happens when it finishes, e.g., for a lot of bouncing: 
// 
// snap.damping = 0.2; 

// you can also slow down the snap by adding some resistance 
// 
// UIDynamicItemBehavior *resistance = [[UIDynamicItemBehavior alloc] initWithItems:@[self.viewToAnimate]]; 
// resistance.resistance = 20.0; 
// resistance.angularResistance = 200.0; 
// [self.animator addBehavior:resistance]; 

[self.animator addBehavior:snap]; 
+0

这很好,我唯一遇到的问题是self.view在纵向时给人像尺寸。 CGRectContainsRect(self.view.frame,imageView.frame) – Jonathan

+0

旋转始终是一个恼人的问题。顺便说一句,如果我的答案适合你,请接受它,谢谢。 – sunkehappy

+0

@Jonathan我的代码不使用'self.view.frame',所以我不确定我是否关注你。我正在使用'imageView.superview.frame',但是你是否说即使在景观中它也返回纵向尺寸? – Rob

1

我认为最简单的方法是检查您的imageView是否已经从您的self.view中消失。

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { 
    if (!CGRectContainsRect(self.view.frame, imageView.frame)){ 
     // Your animation to bounce. 
    } 
} 
+0

我假设这个问题不仅仅是如何确定图像是否已经移动到屏幕外的位置,还有如何确定新的位置。 – Rob