UIScrollView - showing the scroll bar

Viewed 44905

Possibly a simple one!

Does anyone know how to get the scroll bar of a UIScrollView to constantly show?

It displays when the user is scrolling, so they can see what position of the scroll view they are in.

BUT I would like it to constantly show because it is not immediately obvious to the user that scrolling is available

Any advice would be highly appreciated.

11 Answers

No, you can't make them always show, but you can make them temporarily flash.

[myScrollView flashScrollIndicators];

They are scroll indicators, not scroll bars. You can't use them to scroll.

As far as I know, this isn't possible. The only API call which controls displaying the scroll indicator is showsVerticalScrollIndicator and that can only disable displaying the indicator altogether.

You could flashScrollIndicators when the view appears so that the user knows where in the scroll view they are.

This one worked for me:

#define noDisableVerticalScrollTag 836913
#define noDisableHorizontalScrollTag 836914

@implementation UIImageView (ForScrollView) 

- (void) setAlpha:(float)alpha {

    if (self.superview.tag == noDisableVerticalScrollTag) {
        if (alpha == 0 && self.autoresizingMask == UIViewAutoresizingFlexibleLeftMargin) {
            if (self.frame.size.width < 10 && self.frame.size.height > self.frame.size.width) {
                UIScrollView *sc = (UIScrollView*)self.superview;
                if (sc.frame.size.height < sc.contentSize.height) {
                    return;
                }
            }
        }
    }

    if (self.superview.tag == noDisableHorizontalScrollTag) {
        if (alpha == 0 && self.autoresizingMask == UIViewAutoresizingFlexibleTopMargin) {
            if (self.frame.size.height < 10 && self.frame.size.height < self.frame.size.width) {
                UIScrollView *sc = (UIScrollView*)self.superview;
                if (sc.frame.size.width < sc.contentSize.width) {
                    return;
                }
            }
        }
    }

    [super setAlpha:alpha];
}
@end

I got this snippet from here: http://www.developers-life.com/scrollview-with-scrolls-indicators-which-are-shown-all-the-time.html

Swift 3+

1) Timer

var timerForShowScrollIndicator: Timer?

2) Methods

/// Show always scroll indicator in table view
func showScrollIndicatorsInContacts() {
    UIView.animate(withDuration: 0.001) {
        self.tableView.flashScrollIndicators()
    }
}

/// Start timer for always show scroll indicator in table view
func startTimerForShowScrollIndicator() {
    self.timerForShowScrollIndicator = Timer.scheduledTimer(timeInterval: 0.3, target: self, selector: #selector(self.showScrollIndicatorsInContacts), userInfo: nil, repeats: true)
}

/// Stop timer for always show scroll indicator in table view
func stopTimerForShowScrollIndicator() {
    self.timerForShowScrollIndicator?.invalidate()
    self.timerForShowScrollIndicator = nil
}

3) Use

startTimerForShowScrollIndicator in viewDidAppear

stopTimerForShowScrollIndicator in viewDidDisappear

Looking through these answers, most of them are downright scary. Got this working in Swift 5 with the following. It still depends on the scroll view using subviews with class "_UIScrollViewScrollIndicator" - but at least there's no swizzling or app wide categories.

class IndicatorScrollView: UIScrollView {
    
    weak var indicatorTimer: Timer?
    
    override func didMoveToSuperview() {
        super.didMoveToSuperview()
        setupIndicatorTimer()
    }
    
    override func removeFromSuperview() {
        super.removeFromSuperview()
        indicatorTimer?.invalidate()
    }
    
    deinit {
        indicatorTimer?.invalidate()
    }
    
    func setupIndicatorTimer() {
        indicatorTimer?.invalidate()
        indicatorTimer = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(showIndicators), userInfo: nil, repeats: true)
    }
    
    @objc func showIndicators() {
        subviews.forEach {
            if String(describing: type(of: $0)).contains("ScrollIndicator") {
                $0.alpha = 1
            }
        }
    }
}
Related