UIScrollView - showing the scroll bar

前端 未结 10 1716
-上瘾入骨i
-上瘾入骨i 2020-11-27 20:32

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 s

相关标签:
10条回答
  • 2020-11-27 21:10

    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.

    0 讨论(0)
  • 2020-11-27 21:10

    ScrollBar that functions just like the iOS built in one, but you can mess with the color and width.

    -(void)persistantScrollBar
    {
        [persistantScrollBar removeFromSuperview];
        [self.collectionView setNeedsLayout];
        [self.collectionView layoutIfNeeded];
    
        if (self.collectionView.contentSize.height > self.collectionView.frame.size.height + 10)
        {
            persistantScrollBar = [[UIView alloc] initWithFrame:(CGRectMake(self.view.frame.size.width - 10, self.collectionView.frame.origin.y, 5, (self.collectionView.frame.size.height /self.collectionView.contentSize.height) * self.collectionView.frame.size.height))];
            persistantScrollBar.backgroundColor = [UIColor colorWithRed:207/255.f green:207/255.f blue:207/255.f alpha:0.5f];
            persistantScrollBar.layer.cornerRadius = persistantScrollBar.frame.size.width/2;
            persistantScrollBar.layer.zPosition = 0;
            [self.view addSubview:persistantScrollBar];
        }
    }
    
    -(void)scrollViewDidScroll:(UIScrollView *)scrollView
    {
        CGRect rect = persistantScrollBar.frame;
        rect.origin.y =  scrollView.frame.origin.y + (scrollView.contentOffset.y *(self.collectionView.frame.size.height/self.collectionView.contentSize.height));
        rect.size.height = (self.collectionView.frame.size.height /self.collectionView.contentSize.height) * self.collectionView.frame.size.height;
        if ( scrollView.contentOffset.y <= 0 )
        {
            rect.origin.y = scrollView.frame.origin.y;
            rect.size.height = rect.size.height + (scrollView.contentOffset.y);
        }
        else if (scrollView.contentOffset.y + scrollView.frame.size.height >= scrollView.contentSize.height)
        {
            rect.size.height = rect.size.height - ((scrollView.contentOffset.y + scrollView.frame.size.height) - scrollView.contentSize.height);
            rect.origin.y =  (self.collectionView.frame.origin.y + self.collectionView.frame.size.height - 5) - rect.size.height;
        }
    
        persistantScrollBar.frame = rect;
    }
    
    0 讨论(0)
  • 2020-11-27 21:13

    I want to offer my solution. I don't like the most popular variant with category (overriding methods in category can be the reason of some indetermination what method should be called in runtime, since there is two methods with the same selector). I use swizzling instead. And also I don't need to use tags.

    Add this method to your view controller, where you have scroll view (self.categoriesTableView property is a table view where I want to show scroll bars)

    - (void)viewDidAppear:(BOOL)animated {
        [super viewDidAppear:animated];
        // Do swizzling to turn scroll indicator always on
        // Search correct subview with vertical scroll indicator image across tableView subviews
        for (UIView * view in self.categoriesTableView.subviews) {
            if ([view isKindOfClass:[UIImageView class]]) {
                if (view.alpha == 0 && view.autoresizingMask == UIViewAutoresizingFlexibleLeftMargin) {
                    if (view.frame.size.width < 10 && view.frame.size.height > view.frame.size.width) {
                        if (self.categoriesTableView.frame.size.height < self.categoriesTableView.contentSize.height) {
                            // Swizzle class for found imageView, that should be scroll indicator
                            object_setClass(view, [AlwaysOpaqueImageView class]);
                            break;
                        }
                    }
                }
            }
        }
        // Search correct subview with horizontal scroll indicator image across tableView subviews
        for (UIView * view in self.categoriesTableView.subviews) {
            if ([view isKindOfClass:[UIImageView class]]) {
                if (view.alpha == 0 && view.autoresizingMask == UIViewAutoresizingFlexibleTopMargin) {
                    if (view.frame.size.height < 10 && view.frame.size.height < view.frame.size.width) {
                        if (self.categoriesTableView.frame.size.width < self.categoriesTableView.contentSize.width) {
                            // Swizzle class for found imageView, that should be scroll indicator
                            object_setClass(view, [AlwaysOpaqueImageView class]);
                            break;
                        }
                    }
                }
            }
        }
        // Ask to flash indicator to turn it on
       [self.categoriesTableView flashScrollIndicators];
    }
    

    Add new class

    @interface AlwaysOpaqueImageView : UIImageView
    @end
    
    @implementation AlwaysOpaqueImageView
    
    - (void)setAlpha:(CGFloat)alpha {
        [super setAlpha:1.0];
    }
    
    @end
    

    The scroll indicator (vertical scroll indicator in first for cycle and horizontal in second for cycle) will be always at the screen. If you need only one indicator, left only this for cycle in code and remove another one.

    0 讨论(0)
  • 2020-11-27 21:14

    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.

    0 讨论(0)
  • 2020-11-27 21:17

    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

    0 讨论(0)
  • 2020-11-27 21:20

    my solution for show scroll indicators all the time

    #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
    

    UPDATE: This solution cause some issues on 64-bit. For more detail look here

    0 讨论(0)
提交回复
热议问题