UITextView that expands to text using auto layout

前端 未结 16 1917
面向向阳花
面向向阳花 2020-11-28 01:25

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

相关标签:
16条回答
  • 2020-11-28 01:49

    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.

    0 讨论(0)
  • 2020-11-28 01:49

    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
    
    0 讨论(0)
  • 2020-11-28 01:52

    This more of a very important comment

    Key to understanding why vitaminwater's answer works are three things:

    1. Know that UITextView is a subclass of UIScrollView class
    2. Understand how ScrollView works and how its contentSize is calculated. For more see this here answer and its various solutions and comments.
    3. Understand what contentSize is and how its calculated. See here and here. It might also help that setting 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

    0 讨论(0)
  • 2020-11-28 01:56

    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.

    0 讨论(0)
提交回复
热议问题