子视图(UILabel)放置在超级视图(UITextView)中时不遵守约束
Subview (UILabel) doesn't respect the constraints when placed in superview (UITextView)
我尝试了自己的 "placeholder in a UITextView
" 实现。
我的方法是这样的:
我在 UITextView
子 class 中创建了一个 UILabel
,并设置了 UILabel
的约束以匹配其父视图的大小(UITextView
).
这是我创建 UILabel
并将其分配给 awakeFromNib()
中名为 placeholderLabel
的 class 变量的代码:
placeholderLabel = UILabel()
placeholderLabel.text = placeholder
placeholderLabel.numberOfLines = 0
placeholderLabel.lineBreakMode = .byWordWrapping
placeholderLabel.textAlignment = .left
下面的代码是我将 UILabel
添加为子视图的地方,我再次在 awakeFromNib()
:
中设置约束
placeholderLabel.translatesAutoresizingMaskIntoConstraints = false
placeholderLabel.leftAnchor.constraint(equalTo: leftAnchor, constant: textContainerInset.left + 4).isActive = true
placeholderLabel.topAnchor.constraint(equalTo: topAnchor, constant: textContainerInset.top).isActive = true
placeholderLabel.rightAnchor.constraint(equalTo: rightAnchor, constant: textContainerInset.right + 4).isActive = true
placeholderLabel.bottomAnchor.constraint(lessThanOrEqualTo: bottomAnchor, constant: textContainerInset.bottom).isActive = true
我还有一个 属性,我在其中设置占位符的文本,其中我有一个 didSet
观察器,它设置 placeholderLabel
的文本,然后调用 layoutIfNeeded()
为了在 UILabel
扩展到第二(或第三等)行的情况下重新计算约束:
var placeholder: String = "" {
didSet {
placeholderLabel.text = placeholder
layoutIfNeeded()
}
}
问题是我得到以下结果:
UILabel
超出了它的超级视图范围(向右),它似乎不遵守约束。 I 运行视觉调试器确认了同样的事情:
似乎有一个宽度约束遵循 UILabel
的内容宽度,而不是遵循我设置的约束(在这种情况下,它创建的宽度为 431而父视图的宽度是 288).
有什么想念的吗?
with right 应该是负号
placeholderLabel.rightAnchor.constraint(equalTo: rightAnchor, constant: - textContainerInset.right - 4).isActive = true
首先,您必须为右约束的常量使用负值(或者 - 要使用正值 - 切换项目 placeholderLabel.rightAnchor
/ rightAnchor
)。
但真正的问题是 UITextView
是 UIScrollView
的子类。在您的情况下,添加带有大文本的 UILabel
作为子视图并将其边缘限制在文本视图的边缘会导致文本视图的 contentSize
增长。文本视图变为可水平滚动。
在添加标签之前和之后打印文本视图的 contentSize
会导致不同的宽度值(之前:335.0,之后:505.0)。
证明:https://www.dropbox.com/s/eogvl2c5r76c6cl/example.mov?dl=0
您可以通过不创建右侧而是创建宽度约束来解决该问题:
// placeholderLabel.rightAnchor.constraint(equalTo: rightAnchor, constant: -(textContainerInset.right + 4)).isActive = true
placeholderLabel.widthAnchor.constraint(equalTo: widthAnchor, constant: -(textContainerInset.left + 4 + textContainerInset.right + 4)).isActive = true
我尝试了自己的 "placeholder in a UITextView
" 实现。
我的方法是这样的:
我在 UITextView
子 class 中创建了一个 UILabel
,并设置了 UILabel
的约束以匹配其父视图的大小(UITextView
).
这是我创建 UILabel
并将其分配给 awakeFromNib()
中名为 placeholderLabel
的 class 变量的代码:
placeholderLabel = UILabel()
placeholderLabel.text = placeholder
placeholderLabel.numberOfLines = 0
placeholderLabel.lineBreakMode = .byWordWrapping
placeholderLabel.textAlignment = .left
下面的代码是我将 UILabel
添加为子视图的地方,我再次在 awakeFromNib()
:
placeholderLabel.translatesAutoresizingMaskIntoConstraints = false
placeholderLabel.leftAnchor.constraint(equalTo: leftAnchor, constant: textContainerInset.left + 4).isActive = true
placeholderLabel.topAnchor.constraint(equalTo: topAnchor, constant: textContainerInset.top).isActive = true
placeholderLabel.rightAnchor.constraint(equalTo: rightAnchor, constant: textContainerInset.right + 4).isActive = true
placeholderLabel.bottomAnchor.constraint(lessThanOrEqualTo: bottomAnchor, constant: textContainerInset.bottom).isActive = true
我还有一个 属性,我在其中设置占位符的文本,其中我有一个 didSet
观察器,它设置 placeholderLabel
的文本,然后调用 layoutIfNeeded()
为了在 UILabel
扩展到第二(或第三等)行的情况下重新计算约束:
var placeholder: String = "" {
didSet {
placeholderLabel.text = placeholder
layoutIfNeeded()
}
}
问题是我得到以下结果:
UILabel
超出了它的超级视图范围(向右),它似乎不遵守约束。 I 运行视觉调试器确认了同样的事情:
似乎有一个宽度约束遵循 UILabel
的内容宽度,而不是遵循我设置的约束(在这种情况下,它创建的宽度为 431而父视图的宽度是 288).
有什么想念的吗?
with right 应该是负号
placeholderLabel.rightAnchor.constraint(equalTo: rightAnchor, constant: - textContainerInset.right - 4).isActive = true
首先,您必须为右约束的常量使用负值(或者 - 要使用正值 - 切换项目 placeholderLabel.rightAnchor
/ rightAnchor
)。
但真正的问题是 UITextView
是 UIScrollView
的子类。在您的情况下,添加带有大文本的 UILabel
作为子视图并将其边缘限制在文本视图的边缘会导致文本视图的 contentSize
增长。文本视图变为可水平滚动。
在添加标签之前和之后打印文本视图的 contentSize
会导致不同的宽度值(之前:335.0,之后:505.0)。
证明:https://www.dropbox.com/s/eogvl2c5r76c6cl/example.mov?dl=0
您可以通过不创建右侧而是创建宽度约束来解决该问题:
// placeholderLabel.rightAnchor.constraint(equalTo: rightAnchor, constant: -(textContainerInset.right + 4)).isActive = true
placeholderLabel.widthAnchor.constraint(equalTo: widthAnchor, constant: -(textContainerInset.left + 4 + textContainerInset.right + 4)).isActive = true