I have the following code (compile as a standalone file):
#import <Cocoa/Cocoa.h>
@interface AppDelegate : NSObject <NSApplicationDelegate>
@property (strong) NSWindow *window;
@end
@implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)notification {
// Create main window
self.window = [[NSWindow alloc] initWithContentRect:NSMakeRect(100, 100, 800, 600)
styleMask:(NSWindowStyleMaskTitled |
NSWindowStyleMaskClosable |
NSWindowStyleMaskResizable |
NSWindowStyleMaskMiniaturizable)
backing:NSBackingStoreBuffered
defer:NO];
[self.window setTitle:@"Nested ScrollView Demo"];
[self.window makeKeyAndOrderFront:nil];
// Split view controller
NSSplitViewController *splitVC = [[NSSplitViewController alloc] init];
// Sidebar
NSViewController *sidebarVC = [[NSViewController alloc] init];
sidebarVC.view = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 200, 600)];
sidebarVC.view.wantsLayer = YES;
NSSplitViewItem *sidebarItem = [NSSplitViewItem sidebarWithViewController:sidebarVC];
sidebarItem.minimumThickness = 150;
sidebarItem.maximumThickness = 400;
[splitVC addSplitViewItem:sidebarItem];
// Content view controller
NSViewController *contentVC = [[NSViewController alloc] init];
// Vertical scroll view (outer)
NSScrollView *verticalScrollView = [[NSScrollView alloc] initWithFrame:NSMakeRect(0, 0, 600, 600)];
verticalScrollView.automaticallyAdjustsContentInsets = YES;
verticalScrollView.hasVerticalScroller = YES;
verticalScrollView.hasHorizontalScroller = NO;
verticalScrollView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
NSView *verticalContent = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 600, 1200)];
verticalContent.wantsLayer = YES;
verticalContent.layer.backgroundColor = [[NSColor blueColor] CGColor];
[verticalScrollView setDocumentView:verticalContent];
// Add several horizontal scroll sections
CGFloat sectionHeight = 150;
for (int i = 0; i < 5; i++) {
// Horizontal scroll view inside section
NSScrollView *horizontalScroll = [[NSScrollView alloc] initWithFrame:NSMakeRect(0, verticalContent.frame.size.height - (i+1)*sectionHeight - i*20, 600, sectionHeight)];
horizontalScroll.hasHorizontalScroller = YES;
horizontalScroll.hasVerticalScroller = NO;
horizontalScroll.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
NSView *horizontalContent = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 1200, sectionHeight)];
horizontalContent.wantsLayer = YES;
// Add labels horizontally
for (int j = 0; j < 6; j++) {
NSTextField *label = [NSTextField labelWithString:[NSString stringWithFormat:@"Item %d-%d", i+1, j+1]];
label.frame = NSMakeRect(20 + j*200, sectionHeight/2 - 15, 180, 30);
[horizontalContent addSubview:label];
}
horizontalScroll.documentView = horizontalContent;
[verticalContent addSubview:horizontalScroll];
}
contentVC.view = verticalScrollView;
NSSplitViewItem *contentItem = [NSSplitViewItem splitViewItemWithViewController:contentVC];
contentItem.automaticallyAdjustsSafeAreaInsets = YES;
contentItem.minimumThickness = 300;
[splitVC addSplitViewItem:contentItem];
self.window.contentViewController = splitVC;
// Sidebar label
NSTextField *label = [NSTextField labelWithString:@"Sidebar"];
label.translatesAutoresizingMaskIntoConstraints = NO;
[sidebarVC.view addSubview:label];
[NSLayoutConstraint activateConstraints:@[
[label.centerXAnchor constraintEqualToAnchor:sidebarVC.view.centerXAnchor],
[label.centerYAnchor constraintEqualToAnchor:sidebarVC.view.centerYAnchor]
]];
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSApplication *app = [NSApplication sharedApplication];
AppDelegate *delegate = [[AppDelegate alloc] init];
[app setDelegate:delegate];
[app run];
}
return 0;
}
Obviously, since the contents of the right part (the content of the sidebar) has its content inset, the horizontal scrolling views cannot extend to the left beneath the sidebar. I can change line 39 to say verticalScrollView.automaticallyAdjustsContentInsets = NO; which will make the inner horizontal scroll views able to extend below the sidebar, but then I'd lose out on the automatic inset management to not have other content overlap beneath the sidebar. So what can I do here? I've tried manually changing the frame of the inner scroll views to start on a negative x, but that does not allow me to scroll all the way to the leftmost content. I'm hoping I won't have to adjust for safe areas manually for the outer scroll view.
I'd also appreciate tips on how to fix the fact that veritical scrolling doesn't work when your mouse is in a horizontal scroll view.
Thanks!
P.S. same thing also exists on UIKit.