9

I have an NSCollectionView and I would like to hide the horizontal scroll indicators.

I've tried

        collectionView.enclosingScrollView?.verticalScroller?.isHidden = true

But it is not working.

Thank you in advance.

tryKuldeepTanwar
  • 3,490
  • 2
  • 19
  • 49
Jonathanff
  • 409
  • 3
  • 12

10 Answers10

7

hidden didn't work for me too.

The only way I found to hack this, is by changing inset:

(scrollViewCollectionView is of type NSScrollView, this example is while creating NSCollectionView programmatically)

scrollViewCollectionView.documentView?.enclosingScrollView?.scrollerInsets = NSEdgeInsets.init(top: 0, left: 0, bottom: 100, right: 0)

Please note: My NSCollectionView is horizontal, and less then 100 height, this is why this hack resolved in a hidden indicator.

MCMatan
  • 8,623
  • 6
  • 46
  • 85
3

Override hasHorizontalScroller or horizontalScroller to false and nil will cause NSScroller not to be displayed, and NSScrollView will not respond to scroll events.

This means that you can't scroll through NSScrollView's many scrolling methods.

When hasHorizontalScroller = true, horizontalScroller != nil will cause a drawing error.

 class MyScrollView : NSScrollView {

    // !!! Don't use this !!!
    override var hasHorizontalScroller: Bool {
        get {
            // return false will cause NSScroller not to be displayed
            // and NSScrollView will not respond to scroll events,
            // this means that you can't scroll through NSScrollView's many scrolling methods.
            false
        }
        set {
            super.hasHorizontalScroller = newValue
        }
    }

    // !!! Don't use this !!!
    override var horizontalScroller: NSScroller? {
        get {
            // return nil will cause NSScroller not to be displayed,
            // but it still occupies the drawing area of the parent view.
            nil
        }
        set {
            super.horizontalScroller = newValue
        }
    }
}

wrong usage preview1

wrong usage preview2

This is the way to hide NSScroller and respond to scroll events correctly. Only useful in versions above 10.7:

class HiddenScroller: NSScroller {

    // @available(macOS 10.7, *)
    // let NSScroller tell NSScrollView that its own width is 0, so that it will not really occupy the drawing area.
    override class func scrollerWidth(for controlSize: ControlSize, scrollerStyle: Style) -> CGFloat {
        0
    }
}
Jeremy Caney
  • 7,102
  • 69
  • 48
  • 77
Sloaix
  • 39
  • 3
2
  1. Create an outlet for the ScrollView which contains the CollectionView as seen here. I've named mine @IBOutlet weak var collectionViewScrollView: NSScrollView!
  2. in viewDidAppear() function add:

    collectionViewScrollView.scrollerStyle = .legacy collectionViewScrollView.verticalScroller?.isHidden = true - for vertical scroll collectionViewScrollView.horizontalScroller?.isHidden = true - for horizontal scroll

For some reason, in my case it only works if I set the collectionViewScrollView.scrollerStyle to .legacy. Not sure why, but it works.

  • 1
    It worked for me, Its easy to close indicators for `NSCollectionView` but it extends from `NSScrollView` so it makes closed of its indicators. – eemrah Jun 09 '20 at 13:23
1

Setting "Show Vertical Scroller" or "Show Horizontal Scroller" in storyboard doesn't remove the scrollers without setting constrains (height and width) of Bordered Scroll View of Collection View. After I did that and unchecked "Show Vertical Scroller" and "Show Horizontal Scroller" in Attributes Panel in storyboard they disappeared.

Gypsie
  • 78
  • 6
1

I got same problem and just solve it. You can write your own custom NSScrollView and override 2 stored property: hasHorizontalScroller, horizontalScroller, and 1 function scrollWheel(with:). Here's my code:

class MyScrollView: NSScrollView {
    override var hasHorizontalScroller: Bool {
        get {
            return false
        }
        set {
            super.hasHorizontalScroller = newValue
        }
    }

    override var horizontalScroller: NSScroller? {
        get {
            return nil
        }
        set {
            super.horizontalScroller = newValue
        }
    }
    //comment it or use super for scrroling
    override func scrollWheel(with event: NSEvent) {}
}

And don't forget to set Border Scroll View class to MyScrollView in .xib or storyboard. Enjoy it!

isHidden
  • 860
  • 5
  • 16
0

You can also achieve that via storyboard

enter image description here

tryKuldeepTanwar
  • 3,490
  • 2
  • 19
  • 49
0

I also meet the same problem. MCMatan is right. Please adjust the position of scroller to some place invisible.

scrollView.scrollerInsets = NSEdgeInsets.init(top: 0, left: 0, bottom: -10, right: 0)
anergy7
  • 1
  • 5
0

for Swift 4 & 5 in UIKit:

for Horizontal:

collectionView.showsHorizontalScrollIndicator = false

For Vertical:

collectionView.showsVerticalScrollIndicator = false
gandhi Mena
  • 2,115
  • 1
  • 19
  • 20
0
In my case, the horizontal and vertical scroller of the collection scroll view are only hidden if do exactly as follow:

1. In Interface Builder.
1.a. Select Scroll View —> Attributes Inspector:
    + Uncheck Show Horizontal Scroller.
    + Uncheck Show Vertical Scroller.
    + Uncheck Automactically Hide Scroller.
1.b. Select Size Inspector:
    + Uncheck Automatically Adjust.
1.c. Select Clip View —> Size Inspector:
    + Uncheck Automatically Adjust.
2. In code do exactly as follow:

[self.scrollView setBackgroundColor:[NSColor clearColor]];
[self.scrollView setBorderType:NSNoBorder];
[self.scrollView setHasVerticalScroller:NO];
[self.scrollView setHasHorizontalScroller:NO];
[self.scrollView setAutomaticallyAdjustsContentInsets:NO];
[self.scrollView setContentInsets:NSEdgeInsetsMake(0.0, 0.0, -NSHeight([self.scrollView horizontalScroller].frame), -NSWidth([self.scrollView verticalScroller].frame))];
[self.scrollView setScrollerInsets:NSEdgeInsetsMake(0.0, 0.0, -NSHeight([self.scrollView horizontalScroller].frame), -NSWidth([self.scrollView verticalScroller].frame))];
[self.scrollView setScrollEnable:NO];

NSClipView *clipView = (NSClipView *)[self.scrollView documentView];

if ([clipView isKindOfClass:[NSClipView class]])
{
    [clipView setAutomaticallyAdjustsContentInsets:NO];
    [clipView setContentInsets:NSEdgeInsetsZero];
}

Then the NSCollectionView will fit to the Clip View as same width and height without the horizontal and vertical scrollers.
chrisK
  • 148
  • 6
0

If someone still needs it, this one trick should work

collectionView.enclosingScrollView?.horizontalScroller?.alphaValue = 0.0