Как сделать шаг прокрутки вверх или вниз равным высоте ячейки таблицы в NSTableView? - PullRequest
0 голосов
/ 12 октября 2018

У меня есть 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){


}

1 Ответ

0 голосов
/ 13 ноября 2018

Вот мое решение с целью.Целевая строка прокручивается до 2/3 высоты visibleRect, что является компромиссом для моего конкретного приложения.Отрегулируйте математику 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
...