简体   繁体   中英

Subview (UILabel) doesn't respect the constraints when placed in superview (UITextView)

I tried my own "placeholder in a UITextView " implementation.

My approach was this:

I create a UILabel in a UITextView subclass, and I set the constraints of the UILabel to match the size of its superview ( UITextView ).

This is the code where I create the UILabel and assign it to a class variable named placeholderLabel in awakeFromNib() :

placeholderLabel = UILabel()
placeholderLabel.text = placeholder
placeholderLabel.numberOfLines = 0
placeholderLabel.lineBreakMode = .byWordWrapping
placeholderLabel.textAlignment = .left

The following code is where I add the UILabel as a subview, and I set the constraints, again in 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

I also have a property where I set the placeholder's text, where I have a didSet observer, which sets placeholderLabel 's text and then calls layoutIfNeeded() in order to have the constraints recalculated in case the UILabel extends to a second (or third, etc) row:

var placeholder: String = "" {
    didSet {
        placeholderLabel.text = placeholder
        layoutIfNeeded()
    }
}

The issue is that I have the following result:

在此处输入图片说明

The UILabel extends beyond it's superviews bounds (to the right), and it appears that it doesn't respect the constraints. I run the visual debugger which confirmed the same thing:

在此处输入图片说明 在此处输入图片说明

It seems that there is a width constraint which follows the UILabel 's content width instead of following the constraint I have set in place ( in this case it creates a width of 431 whereas the superview's width is 288 ).

Is there something that I miss?

First of all you have to use a negative value for the right constraint's constant (or - to use a positive value - switch the items placeholderLabel.rightAnchor / rightAnchor ).

The real problem though is the fact that UITextView is a subclass of UIScrollView . In your case adding the UILabel with a large text as a subview and constraining its edges to the textview's edges results in the textview's contentSize to grow. The textview becomes horizontally scrollable.

Printing out the textview's contentSize before and after adding the label results in different values for the width (before: 335.0, after: 505.0).

Proof: https://www.dropbox.com/s/eogvl2c5r76c6cl/example.mov?dl=0

You could work around that problem by not creating the right but a width constraint instead:

// 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

正确的应该是负号

placeholderLabel.rightAnchor.constraint(equalTo: rightAnchor, constant: - textContainerInset.right - 4).isActive = true

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM