jjzjj

objective-c - 拖出屏幕时弹回 UIImageView

coder 2024-01-15 原文

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

        }
    }
}

所以我想在右侧和底部实现相同的效果。但是我已经坚持了一段时间。有什么想法吗?

最佳答案

像下面这样的东西怎么样?

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

当我阅读您的代码时,“如果离开左侧,将它移回 View ,距离与屏幕相同的距离”的逻辑。老实说,这对我来说不太有意义(为什么,当弹回时,坐标取决于它离屏幕有多远),但我试图在“离屏右”中尊重这一点,并且“屏幕底部”逻辑。显然,我的逻辑是使用 imageViewsuperview 来确定包含 View 的宽度,但如果这不合适,请将其替换为任何内容。

编辑:

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

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 中,您可以通过使用新的 animationWithDurationusingSpringWithDampening 使 ImageView 的动画回到其原始位置有点弹性和 initialSpringVelocity 参数:

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

关于objective-c - 拖出屏幕时弹回 UIImageView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13427221/

有关objective-c - 拖出屏幕时弹回 UIImageView的更多相关文章

  1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  2. ruby - 主要 :Object when running build from sublime 的未定义方法 `require_relative' - 2

    我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby​​1.9+ 关于ruby-主要:Objectwhenrun

  3. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

  4. 屏幕录制为什么没声音?检查这2项,轻松解决 - 2

    相信很多人在录制视频的时候都会遇到各种各样的问题,比如录制的视频没有声音。屏幕录制为什么没声音?今天小编就和大家分享一下如何录制音画同步视频的具体操作方法。如果你有录制的视频没有声音,你可以试试这个方法。 一、检查是否打开电脑系统声音相信很多小伙伴在录制视频后会发现录制的视频没有声音,屏幕录制为什么没声音?如果当时没有打开音频录制,则录制好的视频是没有声音的。因此,建议在录制前进行检查。屏幕上没有声音,很可能是因为你的电脑系统的声音被禁止了。您只需打开电脑系统的声音,即可录制音频和图画同步视频。操作方法:步骤1:点击电脑屏幕右下侧的“小喇叭”图案,在上方的选项中,选择“声音”。 步骤2:在“声

  5. objective-c - 在设置 Cocoa Pods 和安装 Ruby 更新时出错 - 2

    我正在尝试为我的iOS应用程序设置cocoapods但是当我执行命令时:sudogemupdate--system我收到错误消息:当前已安装最新版本。中止。当我进入cocoapods的下一步时:sudogeminstallcocoapods我在MacOS10.8.5上遇到错误:ERROR:Errorinstallingcocoapods:cocoapods-trunkrequiresRubyversion>=2.0.0.我在MacOS10.9.4上尝试了同样的操作,但出现错误:ERROR:Couldnotfindavalidgem'cocoapods'(>=0),hereiswhy:U

  6. ruby - 你会如何在 Ruby 中表达成语 "with this object, if it exists, do this"? - 2

    在Ruby(尤其是Rails)中,您经常需要检查某物是否存在,然后对其执行操作,例如:if@objects.any?puts"Wehavetheseobjects:"@objects.each{|o|puts"hello:#{o}"end这是最短的,一切都很好,但是如果你有@objects.some_association.something.hit_database.process而不是@objects呢?我将不得不在if表达式中重复两次,如果我不知道实现细节并且方法调用很昂贵怎么办?显而易见的选择是创建一个变量,然后测试它,然后处理它,但是你必须想出一个变量名(呃),它也会在内存中

  7. ruby - 在 Ruby 中,为什么 Array.new(size, object) 创建一个由对同一对象的多个引用组成的数组? - 2

    如thisanswer中所述,Array.new(size,object)创建一个数组,其中size引用相同的object。hash=Hash.newa=Array.new(2,hash)a[0]['cat']='feline'a#=>[{"cat"=>"feline"},{"cat"=>"feline"}]a[1]['cat']='Felix'a#=>[{"cat"=>"Felix"},{"cat"=>"Felix"}]为什么Ruby会这样做,而不是对object进行dup或clone? 最佳答案 因为那是thedocumenta

  8. ruby object.hash - 2

    一个对象的散列值是什么意思?在什么情况下两个对象具有相同的哈希值??还有说Array|Hash不能是Hashkeys,这个跟对象的hash值有关系,为什么? 最佳答案 对于要存储在HashMap或哈希集中的对象,必须满足以下条件:如果认为两个对象相等,则它们的哈希值也必须相等。如果两个对象不被认为是相等的,那么它们的哈希值应该很可能不同(两个不同的对象具有相同哈希值的次数越多,对HashMap/集合的操作性能就越差)。因此,如果两个对象具有相同的哈希值,则很有可能(但不能保证)它们相等。上面“相等”的确切含义取决于散列方法的实现者。

  9. ruby - 为什么 Object 在 Ruby 中既包含内核又继承它? - 2

    在Ruby(1.8.X)中为什么Object既继承了内核又包含了内核?仅仅继承还不够吗?irb(main):006:0>Object.ancestors=>[Object,Kernel]irb(main):005:0>Object.included_modules=>[Kernel]irb(main):011:0>Object.superclass=>nil请注意,在Ruby1.9中情况类似(但更简洁):irb(main):001:0>Object.ancestors=>[Object,Kernel,BasicObject]irb(main):002:0>Object.included

  10. ruby-on-rails - Rails 3 : Looping through array of objects, 忽略数组中的第一个对象? - 2

    在我看来,我正在尝试显示一个对象表,这是我的代码:CategoriesCBB's">然而这是抛出一个错误说:can'tconvertCapabilityBuildingBlockintoArray关系是正确的,错误来self尝试在此处减去数组的第一个对象的行:有什么方法可以忽略数组中的第一个对象来遍历数组吗?谢谢 最佳答案 尝试使用Array.drop-http://www.ruby-doc.org/core/classes/Array.html#M000294 关于ruby-on-ra

随机推荐