iPhone - 获取UIView在整个UIWindow中的位置

239

UIView的位置可以通过view.centerview.frame等方式确定,但这只返回UIView相对于其直接父视图的位置。

我需要确定UIView在整个320x480坐标系统中的位置。例如,如果UIViewUITableViewCell中,则其在窗口中的位置可能会发生剧烈变化,而不考虑其父视图。

是否有任何想法可以实现这一点?

8个回答

365

这很简单:

[aView convertPoint:localPosition toView:nil];

...将本地坐标空间中的点转换为窗口坐标。您可以使用此方法来计算视图在窗口空间中的原点,如下所示:

[aView.superview convertPoint:aView.frame.origin toView:nil];

2014 年修订: 鉴于 Matt__C 评论的受欢迎程度,指出以下内容似乎是合理的:

  1. 旋转设备时不会更改坐标。
  2. 始终以未旋转屏幕的左上角为原点。
  3. 窗口坐标:坐标系统由窗口边界定义。屏幕和设备坐标系统是不同的,不应与窗口坐标混淆。

44
请注意,在toView参数中指定nil会给出设备坐标,如果你不是处于竖屏方向,那么这可能不是你想要的结果。请查看convertpointtoview-in-landscape-mode-giving-wrong-values - Matt__C
2
这个方法一直为我返回 aView.frame.origin。花了我一段时间才意识到我的视图的超级视图本身没有超级视图。 - Dan Abramov
4
如果您的父视图没有超级父视图,那么您的视图根本不应该被看到。 - user4951
@JimThio 要非常精确:如果视图的父视图是一个窗口,它将会可见。在iOS上,UIWindow派生自UIView - Nikolai Ruhe
17
将@Matt__C提供的解决方案改为适用于您的情况,代码如下:[view.superview convertPoint:view.frame.origin toView:[UIApplication sharedApplication].keyWindow.rootViewController.view] - Ghigo
显示剩余8条评论

78

Swift 5+:

let globalPoint = aView.superview?.convert(aView.frame.origin, to: nil)

46
使用扩展功能:
extension UIView{
    var globalPoint :CGPoint? {
        return self.superview?.convert(self.frame.origin, to: nil)
    }
    
    var globalFrame :CGRect? {
        return self.superview?.convert(self.frame, to: nil)
    }
}

2
有时候,父视图不足够,先生。 - famfamfam

36

在 Swift 中:

let globalPoint = aView.superview?.convertPoint(aView.frame.origin, toView: nil)

28

这是根据 @Mohsenasm 的回答和 @Ghigo 的评论结合起来的 Swift 版本。

extension UIView {
    var globalFrame: CGRect? {
        let rootView = UIApplication.shared.keyWindow?.rootViewController?.view
        return self.superview?.convert(self.frame, to: rootView)
    }
}

simple and nice! - nastassia
尽可能好。谢谢。 - Harsh Thakur

4
对我来说很有效 :)
extension UIView {
    var globalFrame: CGRect {
        return convert(bounds, to: window)
    }
}

4

对我而言,这段代码表现最佳:

private func getCoordinate(_ view: UIView) -> CGPoint {
    var x = view.frame.origin.x
    var y = view.frame.origin.y
    var oldView = view

    while let superView = oldView.superview {
        x += superView.frame.origin.x
        y += superView.frame.origin.y
        if superView.next is UIViewController {
            break //superView is the rootView of a UIViewController
        }
        oldView = superView
    }

    return CGPoint(x: x, y: y)
}

1
这对我有用。
view.layoutIfNeeded() // this might be necessary depending on when you need to get the frame

guard let keyWindow = UIApplication.shared.windows.first(where: { $0.isKeyWindow }) else { return }

let frame = yourView.convert(yourView.bounds, to: keyWindow)

print("frame: ", frame)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接