我有一个UIView,我在其中安排了UIButtons。我想找到那些 UIButton 的位置。
我知道
buttons.frame
会给我职位,但它只会给我与其直接超级视图有关的职位。
我们有什么方法可以找到这些按钮相对于 UIButtons 超级视图的超级视图的位置吗?
例如,假设有一个名为“firstView”的 UIView。
然后,我有另一个 UIView,“secondView”。这个“SecondView”是“firstView”的子视图。
然后我将 UIButton 作为“secondView”上的子视图。
->UIViewController.view
--->FirstView A
------->SecondView B
------------>Button
现在,我们有什么方法可以找到 UIButton 相对于“firstView”的位置吗?
您可以使用这个:
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
虽然不特定于层次结构中的按钮,但我发现这更容易可视化和理解:
来自这里:原始来源
对象:
CGPoint point = [subview1 convertPoint:subview2.frame.origin toView:viewController.view];
斯威夫特:
let point = subview1.convert(subview2.frame.origin, to: viewControll.view)
用于转换子视图框架的 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)
框架:(X,Y,宽度,高度)。
因此,即使是超级视图,宽度和高度也不会改变。您可以轻松获得X,Y,如下所示。
X = button.frame.origin.x + [button superview].frame.origin.x;
Y = button.frame.origin.y + [button superview].frame.origin.y;
如果堆叠了多个视图,并且您不需要(或不想)知道您感兴趣的视图之间的任何可能的视图,您可以这样做:
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
下面的情况。
您可以轻松获得如下超级视图。
第二个视图 -> [按钮超级视图]
firstView -> [[按钮超级视图]超级视图]
然后,您就可以获取按钮的位置..
您可以使用这个:
xPosition = [[button superview] superview].frame.origin.x;
yPosition = [[button superview] superview].frame.origin.y;
请注意,无论您需要在视图层次结构中定位的视图有多深(嵌套),以下代码都会起作用。
假设您需要
myView
的位置,它位于 myViewsContainer
内部并且位于视图层次结构的深处,只需遵循以下顺序即可。
let myViewLocation = myViewsContainer.convert(myView.center, to: self.view)
myViewsContainer:您需要的视图所在的视图容器。
myView:您需要其位置的视图。
self.view:主视图
iOS 视图坐标系之间的转换
我们的 UI 具有树形结构,这就是为什么每个级别都使用自己的坐标系
UIView -> CALayer with bounds and frame
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)