我有一个基于视图的NSTableView,有多行(例如20条),每次当我向下滚动滚动条时,我都希望它滚动到下一行。
例如,现在选择第5行,然后向下滚动将选择第6行。但是现在,滚动视图可以停在第5行和第6行之间的中间。
所以我的问题是,当单元格高度为50时,有什么方法可以设置“滚动步长”,然后每次向上/向下滚动50。
NotificationCenter.default.addObserver(self,
selector: #selector(scollDidEnd(_:)),
name: NSScrollView.didLiveScrollNotification,
object: tableView.enclosingScrollView)
@objc func scollDidEnd(_ notification : Notification){
}
答案 0 :(得分:0)
这是我的Objective-C解决方案。目标行滚动到visibleRect高度的2/3,这对我的特定应用程序来说是一个折衷。调整2/3数学以适应您的需求。
#pragma mark -
#pragma mark NSTableView category
@implementation NSTableView (VNSTableViewCategory)
-(NSInteger)visibleRow
{
NSRect theRect = [self visibleRect];
NSRange theRange = [self rowsInRect:theRect];
if ( theRange.length == 0 )
return -1;
else if ( NSLocationInRange( [self editedRow], theRange ) )
return [self editedRow];
else if ( NSLocationInRange( [self clickedRow], theRange ) )
return [self clickedRow];
else if ( NSLocationInRange( [self selectedRow], theRange ) )
return [self selectedRow];
else
return theRange.location + (theRange.length/2);
}
-(NSRange)visibleRows
{
NSRect theRect = [self visibleRect];
NSRange theRange = [self rowsInRect:theRect];
return theRange;
}
-(void)scrollRowToVisibleTwoThirds:(NSInteger)row
{
NSRect theVisRect = [self visibleRect];
NSUInteger numRows = [self numberOfRows];
NSRange visibleRows = [self rowsInRect:theVisRect];
//NSUInteger lastVisibleRow = NSMaxRange(visibleRows);
if ( NSLocationInRange( row, visibleRows ) )
{
if ( row - visibleRows.location < (visibleRows.length * 2 / 3) )
{
// may need to scroll up
if ( visibleRows.location == 0 )
{
// top row at least partially visible. Only scroll if near top
if ( row == 0 || row == 1 )
[self scrollRowToVisible:0];
return;
}
else if ((row - visibleRows.location) > 2 )
return;
}
}
NSRect theRowRect = [self rectOfRow:row];
NSPoint thePoint = theRowRect.origin;
thePoint.y -= theVisRect.size.height / 4; // scroll to 25% from top
if (thePoint.y < 0 )
thePoint.y = 0;
NSRect theLastRowRect = [self rectOfRow:numRows-1];
if ( thePoint.y + theVisRect.size.height > NSMaxY(theLastRowRect) )
[self scrollRowToVisible:numRows-1];
else
{
[self scrollPoint:thePoint]; // seems to be the 'preferred' method of doing this
// kpk note: these other approaches cause redraw artifacts in many situations:
// NSClipView *clipView = [[self enclosingScrollView] contentView];
// [clipView scrollToPoint:[clipView constrainScrollPoint:thePoint]];
// [[self enclosingScrollView] reflectScrolledClipView:clipView];
// [self scrollRowToVisible:row];
// [[[self enclosingScrollView] contentView] scrollToPoint:thePoint];
// [[self enclosingScrollView] reflectScrolledClipView:[[self enclosingScrollView] contentView]];
}
}
@end