为啥我无法检测到我使用 UIKit Dynamics 推离屏幕的 UIView 何时不再可见?

Posted

技术标签:

【中文标题】为啥我无法检测到我使用 UIKit Dynamics 推离屏幕的 UIView 何时不再可见?【英文标题】:Why am I unable to detect when my UIView I push off screen using UIKit Dynamics is no longer visible?为什么我无法检测到我使用 UIKit Dynamics 推离屏幕的 UIView 何时不再可见? 【发布时间】:2014-06-01 08:30:21 【问题描述】:

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

我使用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 值,位于视图控制器的可见区域上方。)

这没问题,除了我给lowestPointx 值真的把一切都搞砸了。如果我选择最小的 X,即最左边的 X,它只会告诉我 UIView 的左下角何时离开屏幕。通常,由于视图可能会根据用户从哪里推动而旋转,右下角可能会在左下角之后离开屏幕,使其过早检测到它。如果我选择中间 X,它只会告诉我中间底部何时消失,等等。我似乎无法弄清楚如何告诉它“给我绝对最低的 y 值。

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

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

【问题讨论】:

【参考方案1】:

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

但您肯定可以在操作块中使用centerbounds。以下代码在与您类似的情况下对我有用:

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!");
    
;

【讨论】:

以上是关于为啥我无法检测到我使用 UIKit Dynamics 推离屏幕的 UIView 何时不再可见?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 fs.readFileSync 不会检测到我的 json 文件

为啥服务器没有检测到我的 python 项目中的更改源代码?

Swift:将 SwiftUI 元素添加到 UIKit 项目:无法正确应用约束

XCUITest 无法检测到我动态生成的 tableView 的可访问性 id

setDelegate 到我的自定义视图控制器落下无法识别的选择器

为啥我无法在 SwiftUI 中检测到使用 CoreBluetooh 的其他蓝牙设备?