拖出屏幕时弹回UIImageView

时间:2012-11-17 02:57:06

标签: objective-c ios uiimageview uitouch

我需要的是当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];

        }
    }
}

所以我想为右侧和底侧实现同样的目标。但是我已经坚持了一段时间。任何想法?

2 个答案:

答案 0 :(得分: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];
    }
}

当我阅读你的代码时,“如果偏离左侧,将其重新移回视图的距离与屏幕相同的距离”。说实话,这对我来说没有多大意义(为什么,当弹回时,坐标取决于它离屏幕有多远),但我试图在“屏幕右侧”和“屏幕底部”逻辑。显然我的逻辑是使用superview imageView来确定包含视图的宽度,但是如果这不合适,则用任何东西替换它。

修改

我个人用手势识别器来做这些事情,例如:

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;
        }];
    }
}

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

- (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 Dynamics添加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];

答案 1 :(得分:1)

我认为最简单的方法是检查imageView是否已超出self.view

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