2017-01-31 85 views
1

我有一个基于视图的NSTableView显示消息/信息的时间线。行高是可变的。新消息经常使用insertRows在桌子的顶部增加插入行时保持相同的NSTableView滚动位置

NSAnimationContext.runAnimationGroup({ (context) in 
    context.allowsImplicitAnimation = true 
    self.myTable.insertRows(at: indexSet, withAnimation: [.effectGap]) 
}) 

虽然用户停留在表的顶部,消息不断被插入在顶部,向下推动现有的:在这种情况下通常的行为。

一切正常,除了如果用户向下滚动,新插入的消息不应该使表滚动

我希望tableView保持它在用户滚动时的位置或用户已向下滚动。

换句话说,如果顶部行100%可见,tableView只能被新插入的行按下。

我试图把桌上的不是很快恢复其位置,这样移动的错觉:

// we're not at the top anymore, user has scrolled down, let's remember where 
let scrollOrigin = self.myTable.enclosingScrollView!.contentView.bounds.origin 
// stuff happens, new messages have been inserted, let's scroll back where we were 
self.myTable.enclosingScrollView!.contentView.scroll(to: scrollOrigin) 

但它不表现为我想。我尝试了很多组合,但我认为我并不理解剪辑视图,滚动视图和表视图之间的关系。

或者,也许我在XY问题区域,并有不同的方式来获得这种行为?

回答

4

忘掉滚动视图,剪辑视图,contentView,documentView并关注表视图。表视图可见部分的底部不应移动。您可能错过了翻转的坐标系。

NSPoint scrollOrigin; 
NSRect rowRect = [self.tableView rectOfRow:0]; 
BOOL adjustScroll = !NSEqualRects(rowRect, NSZeroRect) && !NSContainsRect(self.tableView.visibleRect, rowRect); 
if (adjustScroll) { 
    // get scroll position from the bottom: get bottom left of the visible part of the table view 
    scrollOrigin = self.tableView.visibleRect.origin; 
    if (self.tableView.isFlipped) { 
     // scrollOrigin is top left, calculate unflipped coordinates 
     scrollOrigin.y = self.tableView.bounds.size.height - scrollOrigin.y; 
    } 
} 

// insert row 
id object = [self.arrayController newObject]; 
[object setValue:@"John" forKey:@"name"]; 
[self.arrayController insertObject:object atArrangedObjectIndex:0]; 

if (adjustScroll) { 
    // restore scroll position from the bottom 
    if (self.tableView.isFlipped) { 
     // calculate new flipped coordinates, height includes the new row 
     scrollOrigin.y = self.tableView.bounds.size.height - scrollOrigin.y; 
    } 
    [self.tableView scrollPoint:scrollOrigin]; 
} 

我没有测试“tableView留在它在用户滚动的位置”。

+0

这正是我所需要的。非常感谢! – Moritz