插入行时保持相同的 NSTableView 滚动位置
Keep same NSTableView scrolled position while inserting rows
我有一个基于视图的 NSTableView,显示 messages/informations 的时间线。行高是可变的。使用 insertRows
:
定期在 table 顶部添加新消息
NSAnimationContext.runAnimationGroup({ (context) in
context.allowsImplicitAnimation = true
self.myTable.insertRows(at: indexSet, withAnimation: [.effectGap])
})
当用户停留在 table 的顶部时,消息会一直插入顶部,将现有的消息推到下面:这是这种情况下的常见行为。
一切正常,除了 如果用户向下滚动,新插入的消息不应该 table 滚动 。
我希望 tableView 在用户滚动或向下滚动时保持原样。
换句话说,如果顶行 100% 可见,tableView 应该只被新插入的行下推。
我试图通过像这样快速恢复它的位置来给人一种 table 不动的错觉:
// 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)
但它的行为并不如我所愿。我尝试了很多组合,但我认为我不了解剪辑视图、滚动视图和 table 视图之间的关系。
或者我可能处于 XY 问题区域并且有不同的方式来获得此行为?
忘掉滚动视图、剪辑视图、内容视图、文档视图,专注于 table 视图。 table 视图可见部分的底部不应移动。您可能错过了翻转坐标系。
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];
}
我没有测试 "the tableView to stay where it is while the user scrolls"。
我有一个基于视图的 NSTableView,显示 messages/informations 的时间线。行高是可变的。使用 insertRows
:
NSAnimationContext.runAnimationGroup({ (context) in
context.allowsImplicitAnimation = true
self.myTable.insertRows(at: indexSet, withAnimation: [.effectGap])
})
当用户停留在 table 的顶部时,消息会一直插入顶部,将现有的消息推到下面:这是这种情况下的常见行为。
一切正常,除了 如果用户向下滚动,新插入的消息不应该 table 滚动 。
我希望 tableView 在用户滚动或向下滚动时保持原样。
换句话说,如果顶行 100% 可见,tableView 应该只被新插入的行下推。
我试图通过像这样快速恢复它的位置来给人一种 table 不动的错觉:
// 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)
但它的行为并不如我所愿。我尝试了很多组合,但我认为我不了解剪辑视图、滚动视图和 table 视图之间的关系。
或者我可能处于 XY 问题区域并且有不同的方式来获得此行为?
忘掉滚动视图、剪辑视图、内容视图、文档视图,专注于 table 视图。 table 视图可见部分的底部不应移动。您可能错过了翻转坐标系。
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];
}
我没有测试 "the tableView to stay where it is while the user scrolls"。