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

问题描述 投票:0回答:9

我有一个UIView,我在其中安排了UIButtons。我想找到那些 UIButton 的位置。

我知道

buttons.frame
会给我职位,但它只会给我与其直接超级视图有关的职位。

我们有什么方法可以找到这些按钮相对于 UIButtons 超级视图的超级视图的位置吗?

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

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

然后我将 UIButton 作为“secondView”上的子视图。

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

现在,我们有什么方法可以找到 UIButton 相对于“firstView”的位置吗?

iphone ios uiview uibutton cgrect
9个回答
232
投票

您可以使用这个:

Objective-C

CGRect frame = [firstView convertRect:buttons.frame fromView:secondView];

斯威夫特

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

文档参考:

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


62
投票

虽然不特定于层次结构中的按钮,但我发现这更容易可视化和理解:

来自这里:原始来源

enter image description here

对象:

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)
    }

enter image description here


15
投票

用于转换子视图框架的 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)

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;

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
ViewController.view

这个函数试图做的事情如下:
如果
targetView
没有超级视图,则返回其当前坐标。
如果
targetView's
超级视图不是基本视图(即按钮和
viewcontroller.view
之间还有其他视图),则会检索转换后的坐标并将其传递给下一个
superview

它通过向基本视图移动的视图堆栈继续执行相同的操作。
一旦到达
baseView
,它就会进行最后一次转换并返回。
注意:它不处理
targetView
位于
baseView
下面的情况。


3
投票

您可以轻松获得如下超级视图。

第二个视图 -> [按钮超级视图]
firstView -> [[按钮超级视图]超级视图]

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

您可以使用这个:

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

2
投票

请注意,无论您需要在视图层次结构中定位的视图有多深(嵌套),以下代码都会起作用。

假设您需要

myView
的位置,它位于
myViewsContainer
内部并且位于视图层次结构的深处,只需遵循以下顺序即可。

let myViewLocation = myViewsContainer.convert(myView.center, to: self.view)
  • myViewsContainer:您需要的视图所在的视图容器。

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

  • self.view:主视图


0
投票

iOS 视图坐标系之间的转换

我们的 UI 具有树形结构,这就是为什么每个级别都使用自己的坐标系

UIView -> CALayer with bounds and frame

[iOS 边界和框架]

UIView.bounds
x 和 y - 它是本地坐标系(边界)中的起点,通常但不总是 (0, 0)

UIView.frame
x 和 y - 它是父(超级视图)坐标系中的起点

您可以使用 1 of 4 种方法 将点或矩形从一种坐标系转换为另一种坐标系

viewA has viewB, viewB has viewC
看一下示例:

我们来看看Point的转换方法。它有两种解释,结果相同

将点 viewC 局部坐标系(边界)转换为 viewA 坐标系

let convertTo = viewC.convert(CGPoint(x: 1, y: 1), to: viewA)
print("convertTo: \(convertTo)") //convertTo: (101.0, 101.0)

let convertFrom = viewA.convert(CGPoint(x: 1, y: 1), from: viewC)
print("convertFrom: \(convertFrom)") //convertFrom: (101.0, 101.0)

局部坐标系(边界)。需要注意的是,您的工作是有边界的。例如你将 viewC 旋转 45 度

源代码:

print("viewA frame: \(viewA.frame)") //viewA frame: (0.0, 0.0, 200.0, 200.0)
print("viewA bounds: \(viewA.bounds)") //viewA bounds: (0.0, 0.0, 200.0, 200.0)

print("viewB frame: \(viewB.frame)") //viewB frame: (100.0, 100.0, 100.0, 100.0)
print("viewB bounds: \(viewB.bounds)") //viewB bounds: (0.0, 0.0, 100.0, 100.0)

print("viewC frame: \(viewC.frame)") //viewC frame: (0.0, 0.0, 50.0, 50.0)
print("viewC bounds: \(viewC.bounds)") //viewC bounds: (0.0, 0.0, 50.0, 50.0)

//convert To
// read as convert point from viewC coordinate system to viewA coordinate system
let convertTo = viewC.convert(CGPoint(x: 1, y: 1), to: viewA)
print("convertTo: \(convertTo)") //convertTo: (101.0, 101.0)

//convert From
// read as convert point from viewC coordinate system to viewA coordinate system
let convertFrom = viewA.convert(CGPoint(x: 1, y: 1), from: viewC)
print("convertFrom: \(convertFrom)") //convertFrom: (101.0, 101.0)

//convert Rect
let convertToRect = viewC.convert(CGRect(x: 1, y: 1, width: 5, height: 5), to: viewA)
print("convertToRect: \(convertToRect)") //convertToRect: (101.0, 101.0, 5.0, 5.0)

//transform
viewC.transform = CGAffineTransform(rotationAngle: CGFloat.pi / 4)
print("viewC frame: \(viewC.frame)") //viewC frame: (-10.355339059327374, -10.355339059327378, 70.71067811865476, 70.71067811865476)
print("viewC bounds: \(viewC.bounds)") //viewC bounds: (0.0, 0.0, 50.0, 50.0)

let convertTo2 = viewC.convert(CGPoint(x: 0, y: 0), to: viewA)
print("convertTo2: \(convertTo2)") //(125.0, 89.64466094067262)

© www.soinside.com 2019 - 2024. All rights reserved.