firstresponder
firstresponder

Reputation: 5110

NSTableView content view inset

I am looking to inset the contents of an NSTableView so that there is a gap between the top of the table view and the first cell.

On iOS this is easy with UITableView - achieved by using setContentInset:.

Upvotes: 5

Views: 3257

Answers (4)

Joshua Nozzi
Joshua Nozzi

Reputation: 61228

Turn headers back on and substitute the header view with your own subclass. Override its -drawRect: to draw only your background color. Also override -headerRectOfColumn: to prevent any of the column headers from being drawn. I'm not sure if this prevents column dragging or sorting but I'll bet it does.

Update: Isaiah’s answer from 2019 should now be the correct answer. A lot has changed since my answer!

Upvotes: 3

isaiah
isaiah

Reputation: 455

The question asked how to adjust content insets similar to iOS. The currently selected answer shows how to move the first row down, but that's not quite the same thing. Adjusting the content insets will also move the start of the scrollbar to the inset position, just like iOS. This is useful when placing content underneath a "vibrant" or transparent toolbar.

An NSTableView itself does not have content insets. On macOS content insets are usually part of NSScrollView. To get access to the scroll view of NSTableView's view controller you can use the enclosingScrollview method of NSView, disable automatic adjustment and set the insets like this:

(warning old school Obj-C here)

    self.enclosingScrollView.automaticallyAdjustsContentInsets = NO;
    self.enclosingScrollView.contentInsets = NSEdgeInsetsMake(50.f,0.f,0.f,0.f);

Calling these from viewDidLoad is usually fine, however some types of table views will override your values with their own.

NSOutlineView set to source-list mode comes with lots of default values overridden to make the view look like the Finder sidebar. There is no "clean" way to set the content-insets of these views. They stubbornly override your values, I've found that if you subclass NSOutlineView and overload setFrameSize: it will do the trick. So like this (inside the NSOutlineView subclass):

- (void)setFrameSize:(NSSize)newSize {
    [super setFrameSize:newSize];
    self.enclosingScrollView.automaticallyAdjustsContentInsets = NO;
    self.enclosingScrollView.contentInsets = NSEdgeInsetsMake(100.f,0.f,0.f,0.f);
}

This will do the trick, but the initial scroll position will be strange. Calling scrollToBeginningOfDocument: from the initWithCoder: method of the subclass will scroll it to the correct initial position.

Upvotes: 4

user3722523
user3722523

Reputation: 1790

scrollView.automaticallyAdjustsContentInsets = false
scrollView.contentInsets = NSEdgeInsets(top: 40, left: 0, bottom: 0, right: 0)

Upvotes: 2

k7d
k7d

Reputation: 1

It's not very clean but you can achieve that by having the first row higher than the rest. Implement heightOfRow table delegate method:

- (CGFloat)tableView:(NSTableView *)tableView heightOfRow:(NSInteger)row 
{
  if (row == 0) {
    return normalRowHeight + topPadding;
  } else {
    return normalRowHeight;
  }
}

The drawback is that you would also need to implement custom highlighting and custom cell drawing to take into account the extra space for the first row.

Upvotes: 0

Related Questions