13

I'd like to hide the NSScrollers of NSScrollView. I'm aware of the methods setHasHorizontalScroller: and setHasVerticalScroller:. However, if I disable the scrollers, scrolling in that direction gets disabled as well. I'd like to only hide the scrollers while maintaining the possibility to scroll. Any thoughts on this?

Ashish
  • 2,977
  • 1
  • 14
  • 32
mplappert
  • 1,314
  • 11
  • 18

6 Answers6

12

I was able to do this by doing:

[labelsScrollView setHasHorizontalScroller:YES];
[[labelsScrollView horizontalScroller] setAlphaValue:0];
Mark Bao
  • 896
  • 1
  • 10
  • 19
  • 3
    Thanks, this is still working on macOS 10.13.4 with Swift. I did need to set the `.scrollerStyle` to `.overlay` for it to work though. For some reason with `.legacy` the "background" of the scrollbar is still drawn. – Austin Apr 21 '18 at 21:31
  • 1
    Scroller is not visible, but still can receive touches :0 – Vlad Jun 07 '18 at 07:00
8

The trick of setting alphaValue to zero has issue as invisible scroller still receives touches. Here is what we did in order to solve this (Swift 4).

class InvisibleScroller: NSScroller {

   override class var isCompatibleWithOverlayScrollers: Bool {
      return true
   }

   override class func scrollerWidth(for controlSize: NSControl.ControlSize, scrollerStyle: NSScroller.Style) -> CGFloat {
      return CGFloat.leastNormalMagnitude // Dimension of scroller is equal to `FLT_MIN`
   }

   public override init(frame frameRect: NSRect) {
      super.init(frame: frameRect)
      setupUI()
   }

   required init?(coder: NSCoder) {
      super.init(coder: coder)
      setupUI()
   }

   private func setupUI() {
      // Below assignments not really needed, but why not.
      scrollerStyle = .overlay
      alphaValue = 0
   }
}

Usage:

private class TabBarScrollView: NSScrollView {

   private func setupUI() {

      borderType = .noBorder
      backgroundColor = .clear
      drawsBackground = false

      horizontalScrollElasticity = .none
      verticalScrollElasticity = .none

      automaticallyAdjustsContentInsets = false
      horizontalScroller = InvisibleScroller()
   }
}
Tamás Sengel
  • 55,884
  • 29
  • 169
  • 223
Vlad
  • 6,402
  • 1
  • 60
  • 74
2
if collectionView.enclosingScrollView?.hasHorizontalScroller == true {
  collectionView.enclosingScrollView?.horizontalScroller?.scrollerStyle = .overlay
  collectionView.enclosingScrollView?.horizontalScroller?.alphaValue = 0.0
} else {
  print("horizontalScroller")
}

Make sure horizontal scroller is selected:

enter image description here

aturan23
  • 4,798
  • 4
  • 28
  • 52
Ashish
  • 2,977
  • 1
  • 14
  • 32
1

I'm looking for an answer to this as well since setting hasVerticalScroller = false disables trackpad scrolling for me. In the meantime, my horrible hack is to use the following in my NSScrollView subclass:

self.hasVerticalScroller = true
self.scrollerInsets.right = -999999

The scroller is technically visible, it is just way off the edge of the view. :(

sam
  • 3,399
  • 4
  • 36
  • 51
0

Have you checked the NSScrollView Class Reference ?

[scrollView setHasVerticalScroller:NO];

this method doesn't disable scrolling.

If you still do not want to use that method you can also:

[scrollView setHorizontalScroller:nil];
0xDE4E15B
  • 1,284
  • 1
  • 11
  • 25
-1

This is my solution from sam's answer above:

[myNSScrollView setHasVerticalScroller:YES];
[_myNSScrollView setScrollerInsets:NSEdgeInsetsMake(0, 0, 0, -99999)];

The scroller will be hidden even during the scrolling process.

Bo Yuan
  • 39
  • 1
  • 4