NSTableView row height growth

I have a view based NSTableView in a MacOSX application that structures data nicely. I would like to implement an NSTableView to have row heights that grow with the content of the data entered into one of the NSTextViews. I subclassed the NSTextView to "grow" with the user's text, but the problem is that having a field embedded in the TableView causes the field to be clipped.

Does anyone have any suggestions on how to implement growing line size?

+3


source to share


2 answers


You need to implement -tableView:heightOfRow:

in the delegate of the table view and return the appropriate height for the row. In addition, you need to keep track of the text views to change their height and call them -noteHeightOfRowsWithIndexesChanged:

in the table view when any of them change. To control the height of text views, it should be sufficient to observe NSViewFrameDidChangeNotification

which ones they publish.



(If you use auto-layout, usually in your UI, I think you will have to leave the text views with translatesAutoresizingMaskIntoConstraints

, place them manually, and set their auto-resist masks as needed. Any other restrictions on them. This is because that you want a frame to be set by the text layout manager, but not by auto-layout.)

+4


source


I was able to implement this in Swift 3 (using this great advice and this and this SO answer):

enter image description here

Make sure the table view cell in NSTableView

has a delegated connection to your subclass / view controller that accepts the protocol NSTextFieldDelegate

.

Also give these constraints to resize according to the line height:



enter image description here

In your delegate use this code:

var editedString: String? = nil
var textCellForHeight: NSTextFieldCell = NSTextFieldCell.init()

func control(_ control: NSControl, textShouldBeginEditing fieldEditor: NSText) -> Bool {
    editedString = fieldEditor.string ?? ""
    return true
}

func control(_ control: NSControl, textShouldEndEditing fieldEditor: NSText) -> Bool {
    editedString = nil
    return true
}   

 func control(_ control: NSControl, textView: NSTextView, doCommandBy commandSelector: Selector) -> Bool {
    if commandSelector == #selector(insertNewline(_:)) {
         textView.insertNewlineIgnoringFieldEditor(self)
         editedString = textView.string ?? ""
         //The NSAnimationContext lines get rid of the animation that normally happens when the height changes
         NSAnimationContext.beginGrouping()
         NSAnimationContext.current().duration = 0
         myTableView.noteHeightOfRows(withIndexesChanged: IndexSet.init(integer: selected))
         NSAnimationContext.endGrouping()
         myTable.needsDisplay = true
         return true
    }
    return false
}

func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat {
    if let temp = editedString { //we know it’s currently being edited if it’s not nil
        textCellForHeight.stringValue = temp
        //in my case, there was a specific table column that I knew would be edited
        //you might need to decide on the column width another way.
        let column = myTable.tableColumns[myTable.column(withIdentifier: "TheColumnThatsBeingEdited")]
        let frame: NSRect = NSMakeRect(0, 0, column.width, CGFloat.greatestFiniteMagnitude)
        return textCellForHeight.cellSize(forBounds: frame).height
    }
  return yourStandardHeightCGFloat
}

      

0


source







All Articles