正确调整基于视图的 NSTableView 上的行大小

Posted

技术标签:

【中文标题】正确调整基于视图的 NSTableView 上的行大小【英文标题】:Correctly resizing rows on view-based NSTableView 【发布时间】:2012-08-22 05:51:30 【问题描述】:

当表格视图大小发生变化时,基于视图的NSTableView 具有动态高度的行不会调整其行的大小。当行高来自表格视图的宽度时,这是一个问题(想想填充一列并换行从而扩展行大小的文本块)。

我一直在尝试让 NSTableView 在更改大小时调整其行的大小,但收效甚微:

如果我通过查询 enumerateAvailableRowViewsUsingBlock: 仅调整可见行的大小,则某些不可见行不会调整大小,因此在用户滚动并显示这些行时以旧高度显示。 如果我调整所有行的大小,当有很多行时它会变得明显变慢(在我的 1.8Ghz i7 MacBook Air 中,每个窗口调整 1000 行后大约有 1 秒的延迟)。

有人可以帮忙吗?

这是我检测到表视图大小变化的地方 - 在表视图的委托中:

- (void)tableViewColumnDidResize:(NSNotification *)aNotification

    NSTableView* aTableView = aNotification.object;
    if (aTableView == self.messagesView) 
        // coalesce all column resize notifications into one -- calls messagesViewDidResize: below

        NSNotification* repostNotification = [NSNotification notificationWithName:BSMessageViewDidResizeNotification object:self];
        [[NSNotificationQueue defaultQueue] enqueueNotification:repostNotification postingStyle:NSPostWhenIdle];
    

而以下是上面发布的通知的处理程序,其中可见行被调整大小:

-(void)messagesViewDidResize:(NSNotification *)notification

    NSTableView* messagesView = self.messagesView;

    NSMutableIndexSet* visibleIndexes = [NSMutableIndexSet new];
    [messagesView enumerateAvailableRowViewsUsingBlock:^(NSTableRowView *rowView, NSInteger row) 
        if (row >= 0) 
            [visibleIndexes addIndex:row];
        
    ];
    [messagesView noteHeightOfRowsWithIndexesChanged:visibleIndexes];   

调整所有行大小的替代实现如下所示:

-(void)messagesViewDidResize:(NSNotification *)notification

    NSTableView* messagesView = self.messagesView;      
    NSIndexSet indexes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0,messagesView.numberOfRows)];      
    [messagesView noteHeightOfRowsWithIndexesChanged:indexes];  

注意:这个问题与View-based NSTableView with rows that have dynamic heights 有点相关,但更侧重于响应表格视图的大小变化。

【问题讨论】:

【参考方案1】:

我刚刚经历了这个确切的问题。我所做的是监视滚动视图的内容视图的 NSViewBoundsDidChangeNotification

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(scrollViewContentBoundsDidChange:) name:NSViewBoundsDidChangeNotification object:self.scrollView.contentView];

在处理程序中,获取可见行并调用 noteHeightOfRowsWithIndexesChange:。我在执行此操作时禁用了动画,因此用户在调整大小时不会看到行在视图进入表格时摆动

- (void)scrollViewContentBoundsDidChange:(NSNotification*)notification

    NSRange visibleRows = [self.tableView rowsInRect:self.scrollView.contentView.bounds];
    [NSAnimationContext beginGrouping];
    [[NSAnimationContext currentContext] setDuration:0];
    [self.tableView noteHeightOfRowsWithIndexesChanged:[NSIndexSet indexSetWithIndexesInRange:visibleRows]];
    [NSAnimationContext endGrouping];

这必须快速执行,这样表格才能很好地滚动,但对我来说效果很好。

【讨论】:

对我来说,我等到用户完成调整大小然后重新调整行高。 显然滚动视图内容视图不会发布更改通知,即使调用[self.scrollView.contentView setPostsBoundsChangedNotifications:YES] 似乎 NSViewFrameDidChangNotification 更适合实时调整大小 +1 表示 NSViewFrameDidChangNotification,虽然它实际上拼写为 NSViewFrameDidChangeNotification,但在 Xcode 对我大哭之后我很快就发现了! 非常感谢 swift 代码如下 let column = notification.userInfo?["NSTableColumn"] as? NSTableColumn if let tableView = column?.tableView print("_____TEST2222222") let visibleRowRange = tableView.rowsInRect(tableView.visibleRect) NSAnimationContext.beginGrouping() NSAnimationContext.currentContext().duration = 0 tableView.noteHeightOfRowsWithIndexesChanged(NSIndexSet(indexesInRange: visibleRowRange )) NSAnimationContext.endGrouping()

以上是关于正确调整基于视图的 NSTableView 上的行大小的主要内容,如果未能解决你的问题,请参考以下文章

NSTableView 在 NSSplitView 中显示不正确

基于视图的 NSTableView 中的自定义背景

OSX 基于视图的 NSTableView 字体更改

NSTableView 意外调整大小

基于视图的 NSTableView 的目标操作数据源更新

在 NSWindow 手动调整大小之前,NSTableView 不会布局/调整列大小