2014-10-11 5 views
3

데이터를 멋지게 구조화하는 MacOSX 응용 프로그램에 뷰 기반 NSTableView가 있습니다. NSTableView 중 하나에 입력 한 데이터 내용으로 커지는 행 높이를 갖기 위해 NSTableView를 구현하고 싶습니다. 나는 사용자 텍스트로 "성장"하기 위해 NSTextView를 하위 클래스로 만들었지 만 문제는 TableView에 임베드 된 필드를 사용하면 필드가 잘 리게된다는 것입니다.성장하는 NSTableView 행 높이

성장하는 행 크기를 구현하는 방법에 관해 제안 된 사람이 있습니까?

답변

4

-tableView:heightOfRow:을 테이블 뷰 대리자에 구현하고 해당 행의 높이를 반환해야합니다. 또한 텍스트 뷰의 높이 변화를 모니터링하고 테이블 뷰에서 -noteHeightOfRowsWithIndexesChanged:이 변경되면이를 호출해야합니다. 텍스트보기의 높이를 모니터링하려면 게시 할 NSViewFrameDidChangeNotification을 관찰하면 충분합니다.

(일반적으로 UI에서 자동 레이아웃을 사용하는 경우 translatesAutoresizingMaskIntoConstraints이라는 텍스트보기를 그대로두고 수동으로 배치하고 자동 크기 조정 마스크를 적절하게 설정해야합니다. (텍스트 레이아웃 관리자가 프레임을 설정해야하지만 자동 레이아웃이 필요하지 않기 때문입니다.)

+0

감사 켄, 즉 거대한입니다 도움. -tableView : heightOfRow :를 구현했지만 텍스트 뷰를 모니터링하는 데 문제가 있습니다. IB에서 autoLayout 기능을 가지고 놀면서 나는 원래의 것보다 훨씬 더 깨끗한 솔루션 인 덕분에 확장 된 textView를 얻을 수 있었지만 여전히 텍스트보기를 모니터링하는 데 문제가 있습니다. noteHeighOfRowsWithIndexesChanged : 및 NSViewFrameDidChangeNotification 사용에 대해 좀 더 자세히 설명해 주시겠습니까? – user3932488

+0

어떤면이 문제가됩니까? 테이블에 텍스트 뷰를 추가 할 때마다 컨트롤러 객체를'NSViewFrameDidChangeNotification' 옵저버로'[NSNotificationCenter defaultCenter]'에 "object"포스팅의 텍스트 뷰와 함께 추가합니다. 그런 다음 알림 처리 코드에서'- [NSTableView rowForView :] '를 사용하여 프레임이 변경된보기 (알림의'객체 ')에 해당하는 행을 조회합니다. 그런 다음 테이블 뷰에서'-noteHeightOfRowsWithIndexesChanged :'를 호출하고 행 인덱스를 포함하는 인덱스 세트를 전달합니다. 보기를 제거 할 때 관찰을 중지하십시오. –

+0

좋아, 나는 이것을 정확하게 이해하고 있다고 생각하지 않는다. 구현 - noteHeightofRowsWithIndexesChanged :하지만 전화 받고있는 것 같지 않습니다. AppDelegate에서 NSNotificationCentre를 초기화해야합니까? – user3932488

0

저는 이것을 스위프트 3에서 구현했습니다 (this 위대한 팁과 thisthis SO) 답 :

enter image description here

NSTableView의 테이블보기 셀에 NSTextFieldDelegate 프로토콜을 사용하는 하위 클래스 /보기 컨트롤러에 대한 대리인 연결이 있는지 확인하십시오. 또한

행의 높이에 따라 확인이 크기를 조절하기 위해 그에게 이러한 제약을 줄이 코드 대리자 사용에

enter image description here

:

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 
}