我之前曾问过这个问题,但我对解决方案不太满意。
Automatically adjust size of NSTableView
我想在NSTableView
或NSPopover
中显示NSWindow
。
现在,窗口的大小应该根据表格视图进行调整。
就像Xcode一样:
对于自动布局,这非常简单,您可以将内部视图固定到超级视图。
我的问题是,我无法弄清楚表格视图的最佳高度。 以下代码枚举所有可用行,但它不返回正确的值,因为表视图具有其他元素,如分隔符和表头。
- (CGFloat)heightOfAllRows:(NSTableView *)tableView {
CGFloat __block height;
[tableView enumerateAvailableRowViewsUsingBlock:^(NSTableRowView *rowView, NSInteger row) {
// tried it with this one
height += rowView.frame.size.height;
// and this one
// height += [self tableView:nil heightOfRow:row];
}];
return height;
}
我该如何解决这个问题?如何正确计算表格视图所需的高度。
我应该在哪里运行此代码?
我不想在控制器中实现它,因为它肯定是表视图应该自己处理的东西。
我甚至没有找到任何有用的委托方法。
所以我认为最好是你可以继承NSTableView
那么我的问题2,在哪里实现它?
绝对值得赏金
答案 0 :(得分:5)
您可以查询最后一行的框架以获取表格视图的高度:
- (CGFloat)heightOfTableView:(NSTableView *)tableView
{
NSInteger rows = [self numberOfRowsInTableView:tableView];
if ( rows == 0 ) {
return 0;
} else {
return NSMaxY( [tableView rectOfRow:rows - 1] );
}
}
这假设一个没有边框的封闭滚动视图!
您可以查询tableView.enclosingScrollView.borderType
以检查滚动视图是否有边框。如果是,则需要将边框宽度添加到结果中(两次;底部和顶部)。不幸的是,我不知道如何获得边框宽度。
查询rectOfRow:
的优点是它在与[tableView reloadData];
相同的runloop迭代中工作。根据我的经验,当您首先reloadData
(您将获得之前的高度)时,查询表格视图的框架无法可靠地工作。
答案 1 :(得分:4)
这个答案适用于Swift 4,针对macOS 10.10及更高版本:
<强> 1。答案强>
您可以使用表格视图fittingSize
来计算弹出广告的大小。
tableView.needsLayout = true
tableView.layoutSubtreeIfNeeded()
let height = tableView.fittingSize.height
<强> 2。答案强>
我理解您希望将该代码移出视图控制器,但由于表视图本身对项目数量(仅通过委托)或模型更改一无所知,我会将其放在视图控制器中。自macOS 10.10起,您可以在弹出框内的preferredContentSize
上使用NSViewController
来设置大小。
func updatePreferredContentSize() {
tableView.needsLayout = true
tableView.layoutSubtreeIfNeeded()
let height = tableView.fittingSize.height
let width: CGFloat = 320
preferredContentSize = CGSize(width: width, height: height)
}
在我的示例中,我使用了固定宽度,但您也可以使用计算出的宽度(尚未对其进行测试)。
您希望在数据源发生变化时和/或当您要显示弹出窗口时调用更新方法。
我希望这能解决你的问题!
答案 2 :(得分:3)
Xcode中的Interface Builder自动将NSTableView放入NSScrollView中。 NSScrollView是标题实际所在的位置。在窗口中创建一个NSScrollView作为基本视图,并将NSTableView添加到它:
NSScrollView * scrollView = [[NSScrollView alloc]init];
[scrollView setHasVerticalScroller:YES];
[scrollView setHasHorizontalScroller:YES];
[scrollView setAutohidesScrollers:YES];
[scrollView setBorderType:NSBezelBorder];
[scrollView setTranslatesAutoresizingMaskIntoConstraints:NO];
NSTableView * table = [[NSTableView alloc] init];
[table setDataSource:self];
[table setColumnAutoresizingStyle:NSTableViewUniformColumnAutoresizingStyle];
[scrollView setDocumentView:table];
//SetWindow's main view to scrollView
现在您可以查询scrollView的contentView以查找NSScrollView大小的大小
NSRect rectOfFullTable = [[scrollView contentView] documentRect];
因为NSTableView在NSScrollView中,所以NSTableView将有一个headerView,您可以使用它来查找标题的大小。
通过覆盖reflectScrolledClipView:方法
,可以在表大小更改(标题+行)时更新NSScrollView以更新它的超级视图答案 3 :(得分:2)
我不确定我的解决方案是否比你的解决方案更好,但我认为无论如何我都会提供它。我用它打印视图。我没有使用自动布局。它只适用于绑定 - 需要调整才能使用数据源。
你会看到有一个糟糕的黑客让它发挥作用:我只是在我仔细计算的值上加0.5。
这会考虑间距,但不会显示标题,我不会显示。如果您要显示标题,可以在-tableView:heightOfRow:
方法中添加标题。
在 NSTableView 子类或类别中:
- (void) sizeHeightToFit {
CGFloat height = 0.f;
if ([self.delegate respondsToSelector:@selector(tableView:heightOfRow:)]) {
for (NSInteger i = 0; i < self.numberOfRows; ++i)
height = height +
[self.delegate tableView:self heightOfRow:i] +
self.intercellSpacing.height;
} else {
height = (self.rowHeight + self.intercellSpacing.height) *
self.numberOfRows;
}
NSSize frameSize = self.frame.size;
frameSize.height = height;
[self setFrameSize:frameSize];
}
在表格视图中委托:
// Invoke bindings to get the cell contents
// FIXME If no bindings, use the datasource
- (NSString *) stringValueForRow:(NSInteger) row column:(NSTableColumn *) column {
NSDictionary *bindingInfo = [column infoForBinding:NSValueBinding];
id object = [bindingInfo objectForKey:NSObservedObjectKey];
NSString *keyPath = [bindingInfo objectForKey:NSObservedKeyPathKey];
id value = [[object valueForKeyPath:keyPath] objectAtIndex:row];
if ([value isKindOfClass:[NSString class]])
return value;
else
return @"";
}
- (CGFloat) tableView:(NSTableView *) tableView heightOfRow:(NSInteger) row {
CGFloat result = tableView.rowHeight;
for (NSTableColumn *column in tableView.tableColumns) {
NSTextFieldCell *dataCell = column.dataCell;
if (![dataCell isKindOfClass:[NSTextFieldCell class]]) continue;
// Borrow the prototype cell, and set its text
[dataCell setObjectValue:[self stringValueForRow:row column:column]];
// Ask it the bounds for a rectangle as wide as the column
NSRect cellBounds = NSZeroRect;
cellBounds.size.width = [column width]; cellBounds.size.height = FLT_MAX;
NSSize cellSize = [dataCell cellSizeForBounds:cellBounds];
// This is a HACK to make this work.
// Otherwise the rows are inexplicably too short.
cellSize.height = cellSize.height + 0.5;
if (cellSize.height > result)
result = cellSize.height;
}
return result;
}
答案 4 :(得分:-2)
得到-[NSTableView frame]
NSTableView嵌入在NSScrollView中,但具有完整大小。