如何获取部分从屏幕平移的UIView的可见部分?

时间:2018-09-27 02:00:40

标签: ios objective-c uiview uipangesturerecognizer

我有一个UIView,可以用平移手势将其移动到屏幕的侧面,现在UIView仅部分显示在屏幕上。如何获取在原始视图的坐标中仅包含UIView可见部分和的CGRect?

我已经尝试将CGRectIntersect()UIView.frame的{​​{1}}组合使用,像这样:

[UIScreen mainscreen].bounds

我无法正确解析匹配的坐标系。

2 个答案:

答案 0 :(得分:1)

首先,您需要将位移视图的CGRect转换为主屏幕的坐标系。

您可以尝试

if let mainVC = UIApplication.shared.keyWindow?.rootViewController {
        let translatedRect = mainVC.view.convert(myTestView.frame, from: view)
        let intersection = translatedRect.intersection(mainVC.view.frame)
}

这首先找到主要的rootViewController,然后将视图的框架转换为rootViewController的坐标系,然后找到相交处。即使您将位移视图嵌套在多层视图中,这也将起作用。

答案 1 :(得分:-1)

经过几个小时的实验,我想到了以下解决方案:

// return the part of the passed view that is visible
- (CGRect)getVisibleRect:(UIView *)view {
    // get the root view controller (and it's view is vc.view)
    UIViewController *vc = UIApplication.sharedApplication.keyWindow.rootViewController;

    // get the view's frame in the root view's coordinate system
    CGRect frame = [vc.view convertRect:view.frame fromView:view.superview];

    // get the intersection of the root view bounds and the passed view frame
    CGRect intersection = CGRectIntersection(vc.view.bounds, frame);

    // adjust the intersection coordinates thru any nested views
    UIView *loopView = view;
    do {
        intersection = [loopView convertRect:intersection fromView:loopView.superview];

        loopView = loopView.superview;
    } while (loopView != vc.view);

    return intersection; // may be same as the original view frame
}

我首先尝试将根视图转换为目标视图的坐标,然后在视图框架上执行CGRectIntersect,但这没有用。但是对于以根视图作为其超级视图的UIView,我得到了相反的效果。然后,经过一番摸索,我发现我必须遍历子视图的视图层次结构。

它适用于以超级视图为根视图的UIView,也适用于作为其他视图的子视图的UIView。

我通过在初始视图的这些可见矩形周围绘制边框来对其进行测试,并且效果很好。

但是...如果缩放了UIView(!= 1)以及除根视图之外的另一个UIView的子视图,它将无法正常工作。所得可见rect的原点偏移了一点。如果视图在子视图中,我尝试了几种其他方法来调整原点,但我想不出一种干净的方法。

我已将此方法以及我一直在开发或获取的所有其他“缺失的” UIView方法添加到实用程序UIView类别中。 (Erica Sadun的变换方法...我不值得...)

这确实解决了我正在研究的问题。因此,我将发布有关缩放问题的另一个问题。

编辑: 在解决扩展性问题时,我也为该问题提供了一个更好的答案:

// return the part of the passed view that is visible
- (CGRect)getVisibleRect:(UIView *)view {
    // get the root view controller (and it's view is vc.view)
    UIViewController *vc = UIApplication.sharedApplication.keyWindow.rootViewController;

    // get the view's frame in the root view's coordinate system
    CGRect rootRect = [vc.view convertRect:view.frame fromView:view.superview];

    // get the intersection of the root view bounds and the passed view frame
    CGRect rootVisible = CGRectIntersection(vc.view.bounds, rootRect);

    // convert the rect back to the initial view's coordinate system
    CGRect visible = [view convertRect:rootVisible fromView:vc.view];

    return visible; // may be same as the original view frame
}