iPhone - Get Position of UIView within entire UIWindow
Asked Answered
O

8

241

The position of a UIView can obviously be determined by view.center or view.frame etc. but this only returns the position of the UIView in relation to it's immediate superview.

I need to determine the position of the UIView in the entire 320x480 co-ordinate system. For example, if the UIView is in a UITableViewCell it's position within the window could change dramatically irregardless of the superview.

Any ideas if and how this is possible?

Ogle answered 23/9, 2009 at 11:23 Comment(0)
A
366

That's an easy one:

[aView convertPoint:localPosition toView:nil];

... converts a point in local coordinate space to window coordinates. You can use this method to calculate a view's origin in window space like this:

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

2014 Edit: Looking at the popularity of Matt__C's comment it seems reasonable to point out that the coordinates...

  1. don't change when rotating the device.
  2. always have their origin in the top left corner of the unrotated screen.
  3. are window coordinates: The coordinate system ist defined by the bounds of the window. The screen's and device coordinate systems are different and should not be mixed up with window coordinates.
Anjanetteanjela answered 23/9, 2009 at 11:32 Comment(6)
Be aware that specifying nil in the toView parameter gives you device co-ordinates, which won't be what you want if you are not in portrait orientation. See convertpointtoview-in-landscape-mode-giving-wrong-valuesCountrified
@Matt__C: Specifying nil calculates window coordinates, not device coordinates. If you want device coordinates you have to further convert using UIWindow's conversion methods.Anjanetteanjela
This method kept returning aView.frame.origin for me. It took me a whlie to realize my view's superview did not have a superview itself.Timbale
If your superView did not have a superView your view should not be seen at allYolandayolande
@JimThio To be super-precise: If the view's superview was a window it would be visible. On iOS UIWindow derives fron UIView.Anjanetteanjela
Adapting @Countrified linked solution to your case, it would become: [view.superview convertPoint:view.frame.origin toView:[UIApplication sharedApplication].keyWindow.rootViewController.view]Nanny
L
79

Swift 5+:

let globalPoint = aView.superview?.convert(aView.frame.origin, to: nil)
Lister answered 1/2, 2017 at 19:39 Comment(1)
its OMG.. what a great func!Countersign
P
47

Using extension:

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)
    }
}
Perspex answered 12/9, 2017 at 6:22 Comment(0)
A
37

In Swift:

let globalPoint = aView.superview?.convertPoint(aView.frame.origin, toView: nil)
Autocorrelation answered 30/12, 2015 at 13:41 Comment(0)
T
28

Here is a combination of the answer by @Mohsenasm and a comment from @Ghigo adopted to Swift

extension UIView {
    var globalFrame: CGRect? {
        let rootView = UIApplication.shared.keyWindow?.rootViewController?.view
        return self.superview?.convert(self.frame, to: rootView)
    }
}
Temperate answered 5/7, 2019 at 5:26 Comment(0)
D
4

For me this code worked best:

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)
}
Doggett answered 24/8, 2020 at 13:33 Comment(1)
i don't think using while loop is a good idea in a UI.Plugboard
P
4

Works well for me :)

extension UIView {
    var globalFrame: CGRect {
        return convert(bounds, to: window)
    }
}
Periwig answered 9/7, 2022 at 5:36 Comment(0)
B
2

this worked for me

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)
Boatsman answered 17/11, 2021 at 5:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.