为啥我们不能把 UIView 的子视图放在它的 CALayer 前面?

Posted

技术标签:

【中文标题】为啥我们不能把 UIView 的子视图放在它的 CALayer 前面?【英文标题】:Why can't we put subviews of a UIView in front of its CALayer?为什么我们不能把 UIView 的子视图放在它的 CALayer 前面? 【发布时间】:2019-03-19 15:06:03 【问题描述】:

作为这篇文章的标题,我在this 帖子中找到了关于“我们可以将 UIView 的子视图放在其 CALayer 前面”的答案,但我找不到为什么的答案就是这样。在我看来,将视图作为图层视图的子视图仅表明子视图和图层之间的“更强”顺序。谁能给我解释一下?

【问题讨论】:

【参考方案1】:

每个视图都由 CALayer 支持,层树是视图树的超集。因此,您添加到视图的每个子视图都会将其相应的图层添加到其父视图的图层中。由于它是父层的子层,并且层是从树的顶部向下渲染的,因此您无法更改渲染顺序。

【讨论】:

所以你是说图层的渲染是在所有的视图都被渲染之后进行的?导致图层出现在视图前面? 不,视图永远不会呈现。支持视图的层被渲染。 UIView 本质上是输入和输出的融合(在面向对象的术语中,它是一个 UIResponder 并且它有一个 CALayer)。 layer 完全负责 view 的渲染,view 的很多熟悉的属性其实只是把对应的属性包裹在 layer 上(isHidden、frame、bounds、center 等) 但是如果图层在子视图的图层之前渲染,子图层不应该显示在图层前面吗? 当沿着视图树向下并按同级顺序或同一节点内的 z 位置时,图层会从前渲染(画家算法)。如果您考虑一下,这是有道理的,因为如果您有一个 tabbarcontroller,它会首先呈现,然后是内部的导航控制器,然后是其中的视图控制器,然后是模式警报控制器。 我很抱歉,但我仍然无法理解为什么会这样。当我在调试时检查视图层次结构时,子视图位于图层的前面。但是在模拟器中,子视图出现在图层的后面。为什么结果会不一样?【参考方案2】:

对于任何为此奋斗的人。 您的子视图在父图层下的原因可能是因为您先添加子视图,然后再添加父图层。

你做了什么:

parentView.addSubview(childView)
parentView.layer.addSublayer(someLayer)
// This makes someLayer on top of subview.

你想要什么:

parentView.layer.addSublayer(someLayer)
parentView.addSubview(childView)
// This makes the subview on top of someLayer

要回答您的问题,决定视图之间 z 顺序的唯一因素是您添加图层或视图的顺序。 我认为 addSubview 只是在本机实现下将子层添加到父视图。

【讨论】:

以上是关于为啥我们不能把 UIView 的子视图放在它的 CALayer 前面?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我不能再调整视图大小了?

为啥从自定义 UIView 向 UIButton 添加子视图不显示添加的子视图?

调整旋转 UIView 的子视图大小

无法使用它的子视图高度增加 uiview 的高度?

Swift 4:防止UIView的子视图移动到它的父节点之外

为啥 UIStackView 不堆叠 UILabel 安排的子视图?