0

I have a UITextView in a UIView that I would like the user to be able to show and hide by tapping on it. The UITextView and a constraint of 10 on each side. Currently when a user taps on the view the text does disappear, however you can still see where the UITextView is because there is about one line of space where the UITextView was.

Here is the code I use to adjust the visibility of the UITextView:

if(collapseArray[indexPath.row]){
    cell.noteText?.text = nil
}else{
    cell.noteText?.text = notesArray[indexPath.row]
}

I have tried setting the .isHidden attribute but I get the same results. I was able to get the desired result when I used a UILabel however I would like the text to be editable.

Here is what I am talking about

not hidden: enter image description here

hidden: enter image description here

As you can see there is still a large about of space below the word test, which is a UILabel that has constraints of 10 all the way around.

Here is the code I used for the given answer below:

class NoteTableViewCell: UITableViewCell, UITextViewDelegate {
    
    @IBOutlet weak var noteTitle: UILabel!
    @IBOutlet weak var noteText: UITextView!
    @IBOutlet weak var cardView: UIView!
    
    var textViewHeightConstraint: NSLayoutConstraint!
    
    override class func awakeFromNib() {
        textViewHeightConstraint = noteText.heightAnchor.constraint(equalToConstant: 0)
        textViewHeightConstraint.priority = .defaultLow
        textViewHeightConstraint.isActive = true
    }
}

however this gives me the error:

Instance member 'noteText' cannot be used on type 'NoteTableViewCell'
David
  • 769
  • 1
  • 6
  • 28
  • Hiding won't change the constraints, it will just make it invisible. You might be interested in a `UIStackView`. Else, you could use constraints to do so. – Larme Mar 04 '21 at 17:23
  • This looks like a TableView cell, correct? Is the cell built via XIB or is the layout done programmatically? – jnpdx Mar 04 '21 at 17:27

1 Answers1

1

In your cell, hold a reference to height constraint of textView var textViewHeightConstraint: NSLayoutConstraint!, probably in awakefromNib, be aware that constant is 0 and priority is low

        textViewHeightConstraint = noteText.heightAnchor.constraint(equalToConstant: 0)
        textViewHeightConstraint.priority = .defaultLow
        textViewHeightConstraint.isActive = true

In your logic, toggle the priority of constraint

if(collapseArray[indexPath.row]){
    cell.textViewHeightConstraint.priority = .required //this should set textView height to 0
}else{
    cell.textViewHeightConstraint.priority = .defaultLow //this should set it back
}
cell.textViewHeightConstraint.isActive = true
cell.layoutIfNeeded()

EDIT:

As OP is facing issue with initializing constraint property in awakeFromNib, I am updating the answer below

class NoteTableViewCell: UITableViewCell, UITextViewDelegate {

    @IBOutlet weak var noteTitle: UILabel!
    @IBOutlet weak var noteText: UITextView!
    @IBOutlet weak var cardView: UIView!

    var textViewHeightConstraint: NSLayoutConstraint!

    override func awakeFromNib() {
        super.awakeFromNib()
        textViewHeightConstraint = noteText.heightAnchor.constraint(equalToConstant: 0)
        textViewHeightConstraint.priority = .defaultLow
        textViewHeightConstraint.isActive = true
    }
}

You are supposed to use override func awakeFromNib() not override class func awakeFromNib() also you are supposed to call super.awakeFromNib() before you go ahead and initialize your constraint, super.awakeFromNib() will ensure your IBOutlets are initialized by the time your first statement to initialize constraint executes.

Sandeep Bhandari
  • 19,999
  • 5
  • 45
  • 78
  • I added the variable ```textViewHeightConstraint``` to my Cell class and initialized in the ```AwakeFromNib``` however, I got the error: ```Instance member 'noteText' cannot be used on type 'NoteTableViewCell'``` – David Mar 04 '21 at 18:37
  • you must have made some syntactical mistake check again – Sandeep Bhandari Mar 04 '21 at 18:40
  • This worked but instead of placing the initialization in ```awakeFromNib``` I placed it in ```cellForRowAt``` – David Mar 04 '21 at 18:47
  • @david: Hey sorry It was late night here, so I couldnt reply, you shouldnt be initializing it in `cellForRowAt`, `cellForRowAt` gets called every time cell is scrolled, that means you will end up creating new constraints again and again for each cell, rather than creating constraint only once. `awakeFromNib` is called only once for each cell, that is the perfect place for adding such constraint. statement `textViewHeightConstraint = noteText.heightAnchor.constraint(equalToConstant: 0)` should be executed only once where as you should keep `cell.textViewHeightConstraint.priority =` – Sandeep Bhandari Mar 05 '21 at 04:52
  • in `cellForRowAt`, hence I asked to place `textViewHeightConstraint = noteText.heightAnchor.constraint(equalToConstant: 0)` in awakefromnib where as the logic part (updating constraint priority `cell.textViewHeightConstraint.priority =`) should be placed in `cellForRowAt` – Sandeep Bhandari Mar 05 '21 at 04:52
  • This is the problem I run into when I place the initialization in ```awakeFromNib```: https://stackoverflow.com/questions/25854300/how-to-initialize-properties-that-depend-on-each-other. The given solution here does not work for me – David Mar 08 '21 at 14:36
  • Thats because you did not call `super.awakeFromNib`, call that first and then add your statements, also you have overridden a class func, you were supposed to override instance method – Sandeep Bhandari Mar 08 '21 at 14:58
  • @david: Check the edited answer, and feel free to accept the answer back, once you test it works fine :) BTW question you mentioned and your problem though seem related they are not the same :) – Sandeep Bhandari Mar 08 '21 at 15:03