I have a view that is laid out completely using auto layout programmatically. I have a UITextView in the middle of the view with items above and below it. Everything works f
Summary: Disable scrolling of your text view, and don't constraint its height.
To do this programmatically, put the following code in viewDidLoad
:
let textView = UITextView(frame: .zero, textContainer: nil)
textView.backgroundColor = .yellow // visual debugging
textView.isScrollEnabled = false // causes expanding height
view.addSubview(textView)
// Auto Layout
textView.translatesAutoresizingMaskIntoConstraints = false
let safeArea = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
textView.topAnchor.constraint(equalTo: safeArea.topAnchor),
textView.leadingAnchor.constraint(equalTo: safeArea.leadingAnchor),
textView.trailingAnchor.constraint(equalTo: safeArea.trailingAnchor)
])
To do this in Interface Builder, select the text view, uncheck Scrolling Enabled in the Attributes Inspector, and add the constraints manually.
Note: If you have other view/s above/below your text view, consider using a UIStackView
to arrange them all.
Here's a quick solution:
This problem may occur if you have set clipsToBounds property to false of your textview. If you simply delete it, the problem goes away.
myTextView.clipsToBounds = false //delete this line
This more of a very important comment
Key to understanding why vitaminwater's answer works are three things:
contentOffset
is likely nothing but: func setContentOffset(offset: CGPoint)
{
CGRect bounds = self.bounds
bounds.origin = offset
self.bounds = bounds
}
For more see objc scrollview and understanding scrollview
Combining the three together you'd easily understand that you need allow the the textView's intrinsic contentSize to work along AutoLayout constraints of the textView to drive the logic. It's almost as if you're textView is functioning like a UILabel
To make that happen you need to disable scrolling which basically means the scrollView's size, the contentSize's size and in case of adding a containerView, then the containerView's size would all be the same. When they're the same you have NO scrolling. And you'd have 0
contentOffset
. Having 0
contentOffSet
means you've not scrolled down. Not even a 1 point down! As a result the textView will be all stretched out.
It's also worth nothing that 0
contentOffset
means that the scrollView's bounds and frame are identical.
If you scroll down 5 points then your contentOffset would be 5
, while your scrollView.bounds.origin.y - scrollView.frame.origin.y
would be equal to 5
vitaminwater's answer is working for me.
If your textview's text is bouncing up and down during edit, after setting [textView setScrollEnabled:NO];
, set Size Inspector > Scroll View > Content Insets > Never
.
Hope it helps.