当UIView的bounds原点增加正数时,为什么子视图会向负方向移动?

时间:2018-10-15 18:56:33

标签: ios swift uiview cgrect

这一定是非常简单的事情,可能缺少我的基本数学知识。这很明显(来自this question):

  

视图的框架确定其在超级视图中的位置。查看范围   确定其子视图位置。这意味着,如果您更改视图的   范围,其位置不会更改,但其所有子视图   位置将被更改。

启动Single View App后,视图控制器:

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let v1 = UIView(frame: CGRect(x: 100, y: 100, width: 200, height: 300))
        v1.backgroundColor = UIColor.blue

        let v2 = UIView(frame: v1.bounds.insetBy(dx: 50, dy: 50))
        v2.backgroundColor = UIColor.red

        self.view.addSubview(v1)
        v1.addSubview(v2)
    }

在LLDB控制台上进行检查,这也很清楚:

(lldb) p v1.frame
(CGRect) $R0 = (origin = (x = 100, y = 100), size = (width = 200, height = 300))
(lldb) p v1.bounds
(CGRect) $R1 = (origin = (x = 0, y = 0), size = (width = 200, height = 300))

(lldb) p v2.frame
(CGRect) $R2 = (origin = (x = 50, y = 50), size = (width = 100, height = 200))
(lldb) p v2.bounds
(CGRect) $R3 = (origin = (x = 0, y = 0), size = (width = 100, height = 200))

A red square positioned in the middle of a blue square

v1.bounds.origin.x += 50之后添加v1.bounds.origin.x = 50(或与此有关的v1.addSubview(v2))将导致:

(lldb) p v1.frame
(CGRect) $R0 = (origin = (x = 100, y = 100), size = (width = 200, height = 300))
(lldb) p v1.bounds
(CGRect) $R1 = (origin = (x = 50, y = 0), size = (width = 200, height = 300))

(lldb) p v2.frame
(CGRect) $R2 = (origin = (x = 50, y = 50), size = (width = 100, height = 200))
(lldb) p v2.bounds
(CGRect) $R3 = (origin = (x = 0, y = 0), size = (width = 100, height = 200))

LLDB控制台输出仍然符合我当前的理解,但这就是它的呈现方式:

Red square lined up with the left wall of the blue square

为什么?试图对此进行推理(请参见下文),并且我了解到视图的坐标系是相对的,但是如果在v1的{ {1}},则子视图的有效origin.x应该是frame.origin

2 个答案:

答案 0 :(得分:1)

我在马特·诺伊堡(Matt Neuburg)的Programming iOS 11 book中找到了一个令人满意的答案,举了一个类似的例子:

/* ... */
let v2 = UIView(frame:v1.bounds.insetBy(dx: 10, dy: 10))
/* ... */
v1.bounds.origin.x += 10
v1.bounds.origin.y += 10
  

超级视图的大小或位置没有任何变化。但是子视图   已经向上和向左移动,以便与其超级视图的齐平   左上角。基本上,我们要做的是对   ,“而不是在左上角调用该点   (0.0,0.0),将该点称为(10.0,10.0)。” 因为子视图的框架   原点本身位于(10.0,10.0),子视图现在触摸   超级观看的左上角。更改视图范围的效果   原点似乎是方向性的倒退-我们增加了   原点朝正方向移动,但子视图向   否定方向-但请这样考虑:视图的边界原点   点与其框的左上角重合。

因此,修改origin似乎更像是映射操作,而不是坐标系变换。这也可以解释为什么+= 50= 50的结果相同。

enter image description here

答案 1 :(得分:0)

通过调整v1的 bounds' origin.x,可以将原点扩展到可见矩形之外。 (这是UIScrollView的工作方式。)

如果您改为修改框架的 origin.x,我相信您会看到更符合您期望的结果。