How to draw a transparent NSScroller
Asked Answered
Q

5

5

I'm subclassing NSScroller to try to make it look similar to how "scrollbars" look on iOS. I want it to just be an overlay representing the current position that is drawn OVER what is under it. For whatever reason if I override drawRect for the scroller, I get the bounds filled with white. Is there any way to prevent this so that way I can just be drawing on top of what my NSScroller sub class is over?

Edit: Drawing with clear color seems to bring me close, but it is drawing "too clear" :P It's drawing right to the desktop, when I just want to be drawing down to the window. This picture might make it more clear alt text

Any ideas?

Quadratic answered 15/11, 2010 at 2:44 Comment(0)
M
9

NSView subclasses do all their drawing starting at drawRect. If you override that method in a subclass, you're responsible for doing all of the drawing (whether through you're own methods or calling upon super's methods.) For example, the following code draws just the scroll nob and makes the rest of the scrollbar's frame transparent.

- (void)drawRect:(NSRect)dirtyRect {

    // Do some custom drawing...
    [[NSColor clearColor] set];
    NSRectFill(dirtyRect);

    // Call NSScroller's drawKnob method (or your own if you overrode it)
    [self drawKnob];
  }

This is more of a proof of concept than an actual code suggestion (not sure what implications doing this minimal amount of drawing has on the NSScroller.) NSScroller also has other specific drawing methods you can override / call from an overridden drawRect: method (info available from apple's docs: http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/NSScroller_Class/Reference/Reference.html)

Melicent answered 15/11, 2010 at 5:38 Comment(2)
This gets me very close to what I'm looking for, but is going "too far". See my edit above (the picture is with the draw knob commented out to help illustrate).Quadratic
Found the color I need: [NSColor colorWithCalibratedWhite:0.13 alpha:0.855]Quadratic
C
4

If you leave everything out except for drawing the knob you can get a background-less scroller...

- (void) drawRect: (NSRect) dirtyRect
{
    [self drawKnob];
}
Cervine answered 2/4, 2012 at 3:44 Comment(2)
Though this post is a few years old I just want to mention that this still works using Swift (and is quite easy).Descombes
@Alex This does indeed work. However after the user has finished scrolling, this doesn't hide the scroll bar (even if you are connected via a trackpad).Heterotopia
W
4

Alternatively, you can use RFOverlayScrollView, a nice subclass of NSScroller which is both transparent and auto-hidden; and published under the MIT License.

RFOverlayScrollView

RFOverlayScrollView is an NSScrollView subclass that shows its NSScroller in iOS style even when a mouse is attached.

enter image description here

Wideeyed answered 28/10, 2013 at 23:37 Comment(4)
This one is exactly the same which I was looking for. Thanks for the help. You made my day. Thanks Sir. :)Deckert
Exactly my reaction when I found it ! Don't forget to thank the author too ;)Wideeyed
Fantastic class, works perfectly! (Even on macOS High Sierra - Xcode 9).Heterotopia
The only think I would add to this, is an if statement to the fadeOut method. When you have a USB mouse connected, you still want the scrollbar to be visible (or at least half visible) once the user has stopped scrolling. So in the fadeOut method, check the scrollerStyle to see if you are displaying the standard scrollbar or the auto hide scrollbar. Then set the alpha value accordingly. if (self.scrollerStyle == NSScrollerStyleLegacy) {fadeOutValue = 0.4f;} else { fadeOutValue = 0.0f;}. This enables you to hide the horrible white background as well.Heterotopia
T
1

All you need to do is to set the scrollerView scrollerStyle to NSScrollerStyleOverlay.

Theodore answered 30/5, 2021 at 1:15 Comment(0)
G
0

If you just want to draw on top of what the base class draws, then call [super drawRect:rect] before you do your own drawing.

FWIW, I'm not sure you'll get the effect you want by drawing on top of NSScroller's default drawing. The iOS style scrollers are semi-transparent. If you call super's drawRect:, you'll get the blue scrollers which will be visible through the transparent iOS-style scrollers. You probably want to avoid calling super and just draw everything yourself.

If you want to reuse pieces of the drawing NSScroller does, the class provides many methods for doing this, such as drawKnob, and drawArrow:highlight:, etc.

Glamour answered 15/11, 2010 at 5:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.