0

我正在使用 UIKit Dynamics 将 UIView 推离屏幕,类似于 Tweetbot 在其图像叠加层中执行它的方式。

我使用 a UIPanGestureRecognizer,当他们结束手势时,如果他们超过速度阈值,它就会离开屏幕。

    [self.animator removeBehavior:self.panAttachmentBehavior];

    CGPoint velocity = [panGestureRecognizer velocityInView:self.view];

    if (fabs(velocity.y) > 100) {
        self.pushBehavior = [[UIPushBehavior alloc] initWithItems:@[self.scrollView] mode:UIPushBehaviorModeInstantaneous];
        [self.pushBehavior setTargetOffsetFromCenter:centerOffset forItem:self.scrollView];
        self.pushBehavior.active = YES;

        self.pushBehavior.action = ^{
            CGPoint lowestPoint = CGPointMake(CGRectGetMinX(self.imageView.bounds), CGRectGetMaxY(self.imageView.bounds));
            CGPoint convertedPoint = [self.imageView convertPoint:lowestPoint toView:self.view];

            if (!CGRectIntersectsRect(self.view.bounds, self.imageView.frame)) {
                NSLog(@"outside");
            }
        };

        CGFloat area = CGRectGetWidth(self.scrollView.bounds) * CGRectGetHeight(self.scrollView.bounds);
        CGFloat UIKitNewtonScaling = 5000000.0;
        CGFloat scaling = area / UIKitNewtonScaling;
        CGVector pushDirection = CGVectorMake(velocity.x * scaling, velocity.y * scaling);

        self.pushBehavior.pushDirection = pushDirection;

        [self.animator addBehavior:self.pushBehavior];
    }

当我的视图实际上完全从屏幕上消失时,我很难检测到。

我的观点是设置相当简单。它是一个里面UIScrollView有一个UIImageView。两者都在一个UIViewController. 我UIScrollView使用平移手势移动 ,但想检测图像视图何时离开屏幕。

action块中,我可以在视图移动时对其进行监视,并且我尝试了两种方法:

1.每次action调用块时,找到图像视图的最低点y。将其转换为视图控制器的参考点,当我向上“抛出”视图时,我只是想查看y转换点的值何时小于 0(负)。(这意味着视图中的最低点已经越过y了视图控制器参考点的负值,该参考点位于视图控制器的可见区域之上。)

这工作得很好,除了x我给的价值lowestPoint真的把一切都搞砸了。如果我选择最小的 X,即最左边的 X,它只会告诉我左下角何时离开UIView屏幕。通常情况下,视图可以根据用户从哪里推动而旋转,右下角可能会在左下角之后离开屏幕,使其过早检测到它。如果我选择中间 X,它只会告诉我中间底部何时消失,等等。我似乎不知道如何告诉它“只要给我绝对最低的 y 值。

2.我按照上面的代码尝试过CGRectIntersectsRect,它从来没有说它在外面,即使在它在任何可见区域之外拍摄几秒钟后也是如此。

我究竟做错了什么?我应该如何检测它不再可见?

4

1 回答 1

0

如果您查看UIDynamicItem协议属性,您可以看到它们是center,boundstransform. 所以UIDynamicAnimator实际上只修改了这三个属性。我不太确定frame在动态动画期间会发生什么,但根据我的经验,我可以看出它在动作块中的值并不总是可靠的。可能是因为框架实际上是由 CALayer 基于和计算的center,正如这篇优秀的博客文章中所述。transformbounds

但是你肯定可以在动作块中使用center和。bounds在与您类似的情况下,以下代码对我有用:

CGPoint parentCenter = CGPointMake(CGRectGetMidX(self.view.bounds), CGRectGetMidY(self.view.bounds));
self.pushBehavior.action = ^{
    CGFloat dx = self.imageView.center.x - parentCenter.x;
    CGFloat dy = self.imageView.center.y - parentCenter.y;
    CGFloat distance = sqrtf(dx * dx + dy * dy);
    if(distance > MIN(parentCenter.y + CGRectGetHeight(self.imageView.bounds), parentCenter.x + CGRectGetWidth(self.imageView.bounds))) {
       NSLog(@"Off screen!");
    }
};
于 2014-07-25T14:53:17.087 回答