cocoa-touchuikit

UIkit's UITextView is taking space in the View although if it is empty


enter image description hereI have 3 subViews(2 labels, 1 UITextView) each with different background colour in my VC. I want to show them based on the flag value. The issue is when the UITextview's text empty, the textView has some default width and height(which i did not give) with its background colour whether labels are not taking any width if text is empty

import UIKit

class ViewController: UIViewController {

  @IBOutlet weak var alertTitle: UILabel!
  @IBOutlet weak var alertSubtitle: UITextView!
  @IBOutlet weak var alertMessage: UILabel!
  var fullText: String? =  "dfjgjkd dkjfghjkdg kjdfhkgjh kjfdhkgjhdfkj kjdfshgkj"
  var flag: Bool = true
  override func viewDidLoad() {
      super.viewDidLoad()
      changeText(str: fullText, toggle: flag)
  }
  
  @IBAction func changeText(_ sender: Any) {
      flag = !flag
      changeText(str: fullText, toggle: flag)
  }
  func changeText(str: String? = "", toggle: Bool) {
      alertTitle.text = toggle ? fullText: nil
      alertSubtitle.text = !toggle ? fullText : nil
      alertMessage.text = toggle ? fullText: nil
  }
}

enter image description here


Solution

  • Actually, this is expected behavior. You can open an XIB file, and then insert a UITextView. By default, this textView will have CGSize(240, 128), no matter what the content is, as shown below:

    textView photo

    On the other hand, you can accomplish the same thing with a UILabel. The label now displays CGSize(42, 21)

    label with size photo

    However, when you delete the default Label text, the UILabel is reduced to CGSize(0, 0). This is due of [intrinsicContentSize] (https://developer.apple.com/documentation/uikit/uiview/1622600-intrinsiccontentsize). i.e. the intrinsic content size of a UILabel will be the size of the text (with the font or attributes, if any). Unless you specify some constraints for the label. And this property is different for each kind of view.

    label without size photo

    So, in case you want to hide the UITextView, you need to do it normally with the .isHidden property, or resize it's frame.

    alertSubtitle.isHidden = toggle
    

    Updated: You can put all the views together within a vertical StackView that is aligned with the center of the super view. Then simply toggle it.

    enter image description here

    @IBAction private func toggleAction(_ sender: Any) {
        isToggle.toggle()
        //... other stuffs here
        UIView.animate(withDuration: 0.3) {
            self.alertSubtitle.alpha = self.isToggle ? 0 : 1
            self.alertSubtitle.isHidden = self.isToggle
        }
    }
    
    

    Output:

    enter image description here