I have a UIView, in which I have arranged UIButtons. I want to find the positions of those UIButtons.
I am aware that buttons.frame
will give me the positions, but it will give me positions only with respect to its immediate superview.
Is there is any way we can find the positions of those buttons, withe respect to UIButtons superview's superview?
For instance, suppose there is UIView named "firstView".
Then, I have another UIView, "secondView". This "SecondView" is a subview of "firstView".
Then I have UIButton as a subview on the "secondView".
->UIViewController.view
--->FirstView A
------->SecondView B
------------>Button
Now, is there any way we can find the position of that UIButton, with respect to "firstView"?
You can use this:
Objective C
CGRect frame = [firstView convertRect:buttons.frame fromView:secondView];
Swift
let frame = firstView.convert(buttons.frame, from:secondView)
Documentation reference:
https://developer.apple.com/documentation/uikit/uiview/1622498-convert
Updated for Swift 3
if let frame = yourViewName.superview?.convert(yourViewName.frame, to: nil) {
print(frame)
}
Although not specific to the button in the hierarchy as asked I found this easier to visualize and understand:
From here: original source
ObjC:
CGPoint point = [subview1 convertPoint:subview2.frame.origin toView:viewController.view];
Swift:
let point = subview1.convert(subview2.frame.origin, to: viewControll.view)
Frame: (X,Y,width,height).
Hence width and height wont change even wrt the super-super view. You can easily get the X, Y as following.
X = button.frame.origin.x + [button superview].frame.origin.x;
Y = button.frame.origin.y + [button superview].frame.origin.y;
You can easily get the super-super view as following.
secondView -> [button superview]
firstView -> [[button superview] superview]
Then, You can get the position of the button..
You can use this:
xPosition = [[button superview] superview].frame.origin.x;
yPosition = [[button superview] superview].frame.origin.y;
If there are multiple views stacked and you don't need (or want) to know any possible views between the views you are interested in, you could do this:
static func getConvertedPoint(_ targetView: UIView, baseView: UIView)->CGPoint{
var pnt = targetView.frame.origin
if nil == targetView.superview{
return pnt
}
var superView = targetView.superview
while superView != baseView{
pnt = superView!.convert(pnt, to: superView!.superview)
if nil == superView!.superview{
break
}else{
superView = superView!.superview
}
}
return superView!.convert(pnt, to: baseView)
}
where targetView would be the Button, baseView would be the ViewController.view.
What this function is trying to do is the following:
If targetView has no super view, it's current coordinate is returned.
If targetView's super view is not the baseView (i.e. there are other views between the button and viewcontroller.view), a converted coordinate is retrieved and passed to the next superview.
It continues to do the same through the stack of views moving towards the baseView.
Once it reaches the baseView, it does one last conversion and returns it.
Note: it doesn't handle a situation where targetView is positioned under the baseView.