获取UIView相对于其父视图的父视图的位置

118

我有一个UIView,其中包含了一些UIButtons。我想要找到这些UIButtons的位置。

我知道buttons.frame可以给我这些位置,但它只能相对于它的直接父视图给出位置。

是否有任何方法可以找到这些按钮相对于它们的superview的superview的位置?

例如,假设有一个名为“firstView”的UIView。

然后,我有另一个UIView,“secondView”。这个“secondView”是“firstView”的子视图。

然后我有一个UIButton作为“secondView”的子视图。

->UIViewController.view
--->FirstView A
------->SecondView B
------------>Button

现在,我们有没有办法找到那个UIButton相对于"firstView"的位置呢?

8个回答

229
你可以使用这个:
Objective-C
CGRect frame = [firstView convertRect:buttons.frame fromView:secondView];

Swift

let frame = firstView.convert(buttons.frame, from:secondView)

文档参考:

https://developer.apple.com/documentation/uikit/uiview/1622498-convert

该文档为it技术相关内容,介绍了在iOS开发中UIView类的convert方法。具体实现方式可以参考上述链接。

2
另外,如果您的视图不总是在同一个视图中(比如说,如果您在一个函数中使用它),您可以添加 '...fromView:[button superview]];'。 - mylogon
在SwiftUI中有没有一种方法可以做到这一点? - HillInHarwich

58

虽然这并不特别针对所要求的层次结构中的按钮,但我发现这样更易于可视化和理解:

源自:原始来源

输入图像说明

ObjC:

CGPoint point = [subview1 convertPoint:subview2.frame.origin toView:viewController.view];

快捷:

let point = subview1.convert(subview2.frame.origin, to: viewControll.view)

25

已更新以适用于Swift 3

    if let frame = yourViewName.superview?.convert(yourViewName.frame, to: nil) {

        print(frame)
    }

输入图像描述


14

UIView的扩展,用于转换子视图的框架(受@Rexb答案启发)。

extension UIView {

    // there can be other views between `subview` and `self`
    func getConvertedFrame(fromSubview subview: UIView) -> CGRect? {
        // check if `subview` is a subview of self
        guard subview.isDescendant(of: self) else {
            return nil
        }
        
        var frame = subview.frame
        if subview.superview == nil {
            return frame
        }
        
        var superview = subview.superview
        while superview != self {
            frame = superview!.convert(frame, to: superview!.superview)
            if superview!.superview == nil {
                break
            } else {
                superview = superview!.superview
            }
        }
        
        return superview!.convert(frame, to: self)
    }

}

// usage:
let frame = firstView.getConvertedFrame(fromSubview: buttonView)

这是完美的解决方案!非常感谢! - Dhaval H. Nena

8

框架: (X,Y,宽度,高度).

因此,宽度和高度甚至相对于超级视图而言也不会发生变化。您可以按照以下方式轻松获取X、Y坐标。

X = button.frame.origin.x + [button superview].frame.origin.x;
Y = button.frame.origin.y + [button superview].frame.origin.y;

但是为什么我得到的X,Y值如此之高,比如当我的X为0,0时,使用你的代码行后我得到了180224或者更多? - user285594

5
如果有多个堆叠的视图,而你不需要(或不想)知道在你感兴趣的视图之间可能存在的任何其他视图,你可以这样做:
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)
}

这个函数的目的是将 targetView 按照指定的 baseView 坐标系进行转换。
具体来说,它会执行以下操作:
如果 targetView 没有父视图,则返回其当前坐标。
如果 targetView 的父视图不是 baseView(即在按钮和 viewcontroller.view 之间还有其他视图),则获取转换后的坐标并传递给下一个 superview
它会继续通过视图堆栈执行相同的操作,向着 baseView 移动。
一旦到达 baseView,它会执行最后一次转换并返回结果。
注意:它无法处理 targetView 位于 baseView 下方的情况。


3

您可以如下方法轻松获得超级视图:

secondView -> [button superview]
firstView -> [[button superview] superview]

然后,您可以获取按钮的位置。

您可以使用以下代码:

xPosition = [[button superview] superview].frame.origin.x;
yPosition = [[button superview] superview].frame.origin.y;

2
添加一些解释会使这个答案更有用。 - Sagar Zala

2
请注意,以下代码适用于需要查找视图层次结构中深度(嵌套)不同层级视图位置的情况。
假设您需要查找位于视图层次结构中深处myViewsContainer中的myView位置,请按照以下顺序进行操作。
let myViewLocation = myViewsContainer.convert(myView.center, to: self.view)
  • myViewsContainer: 视图容器,其中包含您需要获取位置的视图。

  • myView: 您需要获取位置的视图。

  • self.view : 主视图


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