通常,当您想到 super 视图与子视图的关系时,人们往往会期望子视图的原点将包含在 super 视图中(通常是 super 视图的原点)。但是,在iOS上的UIKit中,情况似乎并非如此。为什么子视图的原始点是UIWindow(0,0)?

为了演示,以下代码生成了两个UIView,一个是另一个的子视图。由于某种原因,innerView的原点似乎是整个UIWindow的(0,0)。我希望innerView的原点是outerView的原点(其原点由其父视图的中心点决定)。

我得到的是:

self.edgesForExtendedLayout = []

let superView = self.view!
superView.backgroundColor = .white

let outerView = UIView()
outerView.backgroundColor = .cyan
superView.addSubview(outerView)

outerView.snp.makeConstraints { make in
    make.width.equalToSuperview().inset(20)
    make.height.equalTo(superView.snp.height).dividedBy(3)
    make.center.equalToSuperview()
 }

let innerView = UIView()
innerView.backgroundColor = .purple
outerView.addSubview(innerView)
innerView.snp.makeConstraints { (make) in
    make.height.width.equalToSuperview().dividedBy(2)
}

ios - 在使用SnapKit的iOS上,为什么 subview 的原点不是其父 View 的原点?-LMLPHP

我想要的:

添加一条额外的SnapKit约束行会将innerView起点设置为outerView的起点,但是我发现这一步是多余的。
self.edgesForExtendedLayout = []

let superView = self.view!
superView.backgroundColor = .white

let outerView = UIView()
outerView.backgroundColor = .cyan
superView.addSubview(outerView)

outerView.snp.makeConstraints { make in
    make.width.equalToSuperview().inset(20)
    make.height.equalTo(superView.snp.height).dividedBy(3)
    make.center.equalToSuperview()
 }

let innerView = UIView()
innerView.backgroundColor = .purple
outerView.addSubview(innerView)
innerView.snp.makeConstraints { (make) in
    make.top.left.equalToSuperview() // Set origins equal
    make.height.width.equalToSuperview().dividedBy(2)
}

ios - 在使用SnapKit的iOS上,为什么 subview 的原点不是其父 View 的原点?-LMLPHP

到目前为止,这可能是对iOS中视图层次结构的一个基本误解,因为我一直依靠Storyboard。这是我首次涉足iOS上的程序化UI,因此我仍会全神贯注于所有细微差别。现在,证据使我相信,每个视图(无论它在视图层次结构中的位置如何)都始于键UIWindow的位置(0,0)。

最佳答案

每个视图中都有一个新的坐标空间。该窗口无法确定没有原点的子视图的原点。关于示例的最有趣的事情是,您没有给紫色视图画框,因此也没有原点。如果要打印紫色的原点,则它将是紫色的高度和宽度的一半的负数作为相对于 super 视图的原点。最主要的是通过自动布局或分配点为其指定原点。我想我们很幸运能够建立一个起源。这是一个在屏幕快照中添加视图的示例。

import UIKit

class MeasureViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        //view will start at 0,0 of superview which is the main view and be the same size

        let green = UIView(frame: CGRect(x: 0, y: 0, width: self.view.bounds.width, height: self.view.bounds.height))
        green.backgroundColor = .green
        self.view.addSubview(green)

        //first inside view  half of outers width and height
        let blue = UIView(frame: CGRect(x: 0, y: 0, width: green.bounds.midX, height: green.bounds.midY))
        blue.backgroundColor = .blue
        // in this case it is self.view.center and outer.center but won't always be just works because coordinate space matches
        blue.center = green.center
        green.addSubview(blue)

        let white = UIView(frame: CGRect(x: 0, y: 0, width: blue.bounds.midX, height: blue.bounds.midY))
        //will not be in the center of firstInside because it is using the coordinate derived from outer
        white.center = blue.center
        white.backgroundColor = .white
        blue.addSubview(white)

        let redDot = UIView(frame: CGRect(x: 0, y: 0, width: 10, height: 10))
        redDot.layer.cornerRadius = 5
        redDot.backgroundColor = .red
        //will be the center of blue center because it is half the width and height and be correct
        redDot.center = CGPoint(x: blue.bounds.midX, y: blue.bounds.midY)
        blue.addSubview(redDot)

        //same size as white view above but no origin.  this is bad
        let noOriginView = UIView()
        noOriginView.backgroundColor = .cyan
        noOriginView.bounds.size = CGSize(width: blue.bounds.midX, height: blue.bounds.midY)

        blue.addSubview(noOriginView)
        print("Test withoutFrame \(noOriginView.frame.origin)")
    }

}

说明和屏幕截图
ios - 在使用SnapKit的iOS上,为什么 subview 的原点不是其父 View 的原点?-LMLPHP

这些基本原理适用于手动布局,自动布局和Snapkit。使用自动布局和Snapkit时,您不会直接设置点和边界,但是需要约束来做同样的事情。

使用自动版式:
经过对Autolayout的大量测试之后,我确实认为如果视图缺少位置约束,则将其转换为窗口的0,0,这意味着实际原点将为x,y的负值,并且上面的示例将调整为将原点转换为窗口协调空间。

关于ios - 在使用SnapKit的iOS上,为什么 subview 的原点不是其父 View 的原点?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/45395566/

10-09 17:53
查看更多