基于视图的NSTableView具有动态高度的行

我有一个基于视图的应用程序NSTableView。在此表视图中,我有一些行,这些行的单元格的内容由NSTextField启用了自动换行的多行组成。根据的文本内容,NSTextField显示单元格所需的行大小会有所不同。

我知道我可以实现该NSTableViewDelegate方法- tableView:heightOfRow:返回高度,但是高度将基于上的自动换行来确定NSTextField。的自动换行NSTextField类似地基于NSTextFieldis的宽度……由的宽度决定NSTableView

太…我想我的问题是……什么是好的设计模式?似乎我尝试的所有操作都变得混乱不堪。由于TableView需要了解单元格的高度才能对其进行布局...并且NSTextField需要了解其布局来确定自动换行...并且单元格需要了解自动换行来确定其高度...这是一个圆形的混乱局面...这让我发疯

有什么建议吗?

如果重要的话,最终结果也将具有可编辑的内容NSTextFields,可以调整其大小以适应其中的文本。我已经在视图级别进行此操作,但是tableview尚未调整单元格的高度。我认为一旦解决了高度问题,我将使用- noteHeightOfRowsWithIndexesChanged方法通知表格视图高度已更改……但是仍然要向委托人询问高度……因此,我很困惑。

提前致谢!


慕容708150
浏览 1004回答 3
3回答

慕妹3146593

这是鸡和鸡蛋的问题。表格需要知道行高,因为它确定了给定视图的位置。但是,您希望视图已经存在,因此可以使用它来计算行高。那么,哪个先出现?答案是保留额外的NSTableCellView(或用作“单元格视图”的任何视图)周围,仅用于测量视图的高度。在tableView:heightOfRow:委托方法中,访问模型的“行”并设置objectValueon NSTableCellView。然后将视图的宽度设置为表格的宽度,然后(无论您要执行什么操作)找出该视图所需的高度。返回该值。请勿noteHeightOfRowsWithIndexesChanged:在委托方法tableView:heightOfRow:或viewForTableColumn:row:!中调用 那是不好的,并且会引起大麻烦。要动态更新高度,那么您应该做的是响应文本更改(通过目标/动作)并重新计算该视图的计算高度。现在,请勿动态更改NSTableCellView的高度(或任何用作“单元格视图”的视图)。该表必须控制该视图的框架,如果尝试设置该视图,您将与之抗争。相反,在计算高度的文本字段的目标/操作中,调用 noteHeightOfRowsWithIndexesChanged:,这将使表调整该行的大小。假设您已经在子视图(即的子视图NSTableCellView)上设置了自动调整大小的蒙版设置,那么应该可以调整大小!如果不是,请首先对子视图的调整大小蒙版进行操作,以使行高度可变的东西正确无误。不要忘记noteHeightOfRowsWithIndexesChanged:默认设置动画。要使其不动画,请执行以下操作:[NSAnimationContext beginGrouping];[[NSAnimationContext currentContext] setDuration:0];[tableView noteHeightOfRowsWithIndexesChanged:indexSet];[NSAnimationContext endGrouping];PS:我对Apple Dev论坛上发布的问题的回答要多于堆栈溢出。PSS:我写了基于视图的NSTableView

慕妹3242003

根据Corbin的回答(顺便说一句,感谢您对此发表一些看法):Swift 3,基于视图的NSTableView,带有适用于macOS 10.11(及更高版本)的自动布局我的设置:我有一个NSTableCellView使用自动版式布局的布局。它包含(除其他元素外)多行NSTextField,最多可包含2行。因此,整个单元格视图的高度取决于此文本字段的高度。我更新告诉表格视图两次来更新高度:1)当表格视图调整大小时:func tableViewColumnDidResize(_ notification: Notification) {&nbsp; &nbsp; &nbsp; &nbsp; let allIndexes = IndexSet(integersIn: 0..<tableView.numberOfRows)&nbsp; &nbsp; &nbsp; &nbsp; tableView.noteHeightOfRows(withIndexesChanged: allIndexes)}2)当数据模型对象更改时:tableView.noteHeightOfRows(withIndexesChanged: changedIndexes)这将导致表格视图向其委托要求新的行高。func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat {&nbsp; &nbsp; // Get data object for this row&nbsp; &nbsp; let entity = dataChangesController.entities[row]&nbsp; &nbsp; // Receive the appropriate cell identifier for your model object&nbsp; &nbsp; let cellViewIdentifier = tableCellViewIdentifier(for: entity)&nbsp; &nbsp; // We use an implicitly unwrapped optional to crash if we can't create a new cell view&nbsp; &nbsp; var cellView: NSTableCellView!&nbsp; &nbsp; // Check if we already have a cell view for this identifier&nbsp; &nbsp; if let savedView = savedTableCellViews[cellViewIdentifier] {&nbsp; &nbsp; &nbsp; &nbsp; cellView = savedView&nbsp; &nbsp; }&nbsp; &nbsp; // If not, create and cache one&nbsp; &nbsp; else if let view = tableView.make(withIdentifier: cellViewIdentifier, owner: nil) as? NSTableCellView {&nbsp; &nbsp; &nbsp; &nbsp; savedTableCellViews[cellViewIdentifier] = view&nbsp; &nbsp; &nbsp; &nbsp; cellView = view&nbsp; &nbsp; }&nbsp; &nbsp; // Set data object&nbsp; &nbsp; if let entityHandler = cellView as? DataEntityHandler {&nbsp; &nbsp; &nbsp; &nbsp; entityHandler.update(with: entity)&nbsp; &nbsp; }&nbsp; &nbsp; // Layout&nbsp; &nbsp; cellView.bounds.size.width = tableView.bounds.size.width&nbsp; &nbsp; cellView.needsLayout = true&nbsp; &nbsp; cellView.layoutSubtreeIfNeeded()&nbsp; &nbsp; let height = cellView.fittingSize.height&nbsp; &nbsp; // Make sure we return at least the table view height&nbsp; &nbsp; return height > tableView.rowHeight ? height : tableView.rowHeight}首先,我们需要获取模型对象的行(entity)和适当的单元格视图标识符。然后,我们检查是否已经为此标识符创建了视图。为此,我们必须维护一个列表,其中包含每个标识符的单元格视图:// We need to keep one cell view (per identifier) aroundfileprivate var savedTableCellViews = [String : NSTableCellView]()如果没有保存,则需要创建(并缓存)一个新的。我们使用模型对象更新单元格视图,并告诉它根据当前表视图宽度重新布局所有内容。fittingSize然后可以将该高度用作新的高度。
打开App,查看更多内容
随时随地看视频慕课网APP