ios Changing UIScrollView scrollbar color to different colors

后端 未结 17 2350
我在风中等你
我在风中等你 2020-12-05 07:16

How can we change color of UIScrollview\'s scroll indicator to something like blue, green etc.

I know we can change it to white, black. But other then these colors.

相关标签:
17条回答
  • 2020-12-05 07:26

    in IOS 13

    Since iOS13 scroll indicators have class _UIScrollViewScrollIndicator, not UIImageView.

    Many people used code like

    let verticalIndicator: UIImageView = (scrollView.subviews[(scrollView.subviews.count - 1)] as! UIImageView)
    

    It's not good idea, because they promised that last subview will be UIImageView :). Now it's not and they can get crash.

    You can try following code to get scrollView indicators:

    extension UIScrollView {
    
        var scrollIndicators: (horizontal: UIView?, vertical: UIView?) {
    
            guard self.subviews.count >= 2 else {
                return (horizontal: nil, vertical: nil)
            }
    
            func viewCanBeScrollIndicator(view: UIView) -> Bool {
                let viewClassName = NSStringFromClass(type(of: view))
                if viewClassName == "_UIScrollViewScrollIndicator" || viewClassName == "UIImageView" {
                    return true
                }
                return false
            }
    
            let horizontalScrollViewIndicatorPosition = self.subviews.count - 2
            let verticalScrollViewIndicatorPosition = self.subviews.count - 1
    
            var horizontalScrollIndicator: UIView?
            var verticalScrollIndicator: UIView?
    
            let viewForHorizontalScrollViewIndicator = self.subviews[horizontalScrollViewIndicatorPosition]
            if viewCanBeScrollIndicator(view: viewForHorizontalScrollViewIndicator) {
                horizontalScrollIndicator = viewForHorizontalScrollViewIndicator
            }
    
            let viewForVerticalScrollViewIndicator = self.subviews[verticalScrollViewIndicatorPosition]
            if viewCanBeScrollIndicator(view: viewForVerticalScrollViewIndicator) {
                verticalScrollIndicator = viewForVerticalScrollViewIndicator
            }
            return (horizontal: horizontalScrollIndicator, vertical: verticalScrollIndicator)
        }
    
    }
    

    If you need only one (h or v indicator) - it's better to cut this func and keep only one you need (to improve perfomance).

    Also it would be good to call update func inside of DispatchQueue, to keep smoothness of scrolling.

    func scrollViewDidScroll(_ scrollView: UIScrollView) {
       DispatchQueue.main.async {
           scrollView.updateCustomScrollIndicatorView()
       }
    }
    
    0 讨论(0)
  • 2020-12-05 07:29

    please use below code on iOS Renderer

     private bool _layouted;
     public override void LayoutSubviews()
     {
           base.LayoutSubviews();
           if (!_layouted)
           {
                this.Layer.BorderColor = UIColor.Red.CGColor;
                var Verticalbar = (UIImageView)this.Subviews[this.Subviews.Length - 1];
    
                Verticalbar.BackgroundColor = Color.FromHex("#0099ff").ToUIColor();
                var Horizontlebar = (UIImageView)this.Subviews[this.Subviews.Length - 2];
    
                Horizontlebar.BackgroundColor = Color.FromHex("#0099ff").ToUIColor();
                _layouted = true;
           }
    }
    
    0 讨论(0)
  • 2020-12-05 07:32

    I ran into the same problem recently so I decided to write a category for it.

    https://github.com/stefanceriu/UIScrollView-ScrollerAdditions

    [someScrollView setVerticalScrollerTintColor:someColor]; 
    [someScrollView setHorizontalScrollerTintColor:someColor];`
    

    It blends it with the original image so only the color will change. On the other hand, it can also be modified to provide a custom image for the scrollers to use.

    0 讨论(0)
  • 2020-12-05 07:36

    This is how the color of the scroll bar is changed:

        //scroll view  
        UIScrollView *scView = [[UIScrollView alloc] init];  
        scView.frame = self.view.bounds; //scroll view occupies full parent views  
        scView.contentSize = CGSizeMake(400, 800);  
        scView.backgroundColor = [UIColor lightGrayColor];  
        scView.indicatorStyle = UIScrollViewIndicatorStyleBlack;  
        scView.showsHorizontalScrollIndicator = NO;  
        scView.showsVerticalScrollIndicator = YES;  
        scView.scrollEnabled = YES;  
        [self.view addSubview: scView];
    
    0 讨论(0)
  • 2020-12-05 07:38

    Unfortunately you can't, of course you can always roll your own. These are your options:

    UIScrollViewIndicatorStyleDefault:

    The default style of scroll indicator, which is black with a white border. This style is good against any content background.

    UIScrollViewIndicatorStyleBlack:

    A style of indicator which is black and smaller than the default style. This style is good against a white content background.

    UIScrollViewIndicatorStyleWhite:

    A style of indicator is white and smaller than the default style. This style is good against a black content background.

    0 讨论(0)
  • 2020-12-05 07:38

    Based on the answer of @Alex (https://stackoverflow.com/a/58415249/3876285), I'm posting just a little improvement to change the color of scroll indicators.

    extension UIScrollView {
    
        var scrollIndicators: (horizontal: UIView?, vertical: UIView?) {
    
            guard self.subviews.count >= 2 else {
                return (horizontal: nil, vertical: nil)
            }
    
            func viewCanBeScrollIndicator(view: UIView) -> Bool {
                let viewClassName = NSStringFromClass(type(of: view))
                if viewClassName == "_UIScrollViewScrollIndicator" || viewClassName == "UIImageView" {
                    return true
                }
                return false
            }
    
            let horizontalScrollViewIndicatorPosition = self.subviews.count - 2
            let verticalScrollViewIndicatorPosition = self.subviews.count - 1
    
            var horizontalScrollIndicator: UIView?
            var verticalScrollIndicator: UIView?
    
            let viewForHorizontalScrollViewIndicator = self.subviews[horizontalScrollViewIndicatorPosition]
            if viewCanBeScrollIndicator(view: viewForHorizontalScrollViewIndicator) {
                horizontalScrollIndicator = viewForHorizontalScrollViewIndicator.subviews[0]
            }
    
            let viewForVerticalScrollViewIndicator = self.subviews[verticalScrollViewIndicatorPosition]
            if viewCanBeScrollIndicator(view: viewForVerticalScrollViewIndicator) {
                verticalScrollIndicator = viewForVerticalScrollViewIndicator.subviews[0]
            }
            return (horizontal: horizontalScrollIndicator, vertical: verticalScrollIndicator)
        }
    
    }
    

    If you don't add .subviews[0], you will get the deeper view and when you try to change the color of the indicator, this will appear with a weird white effect. That's because there is another view in front of it:

    By adding .subviews[0] to each indicator view, once you try to change the color by calling:

    override func scrollViewDidScroll(_ scrollView: UIScrollView) {
        DispatchQueue.main.async() {
            scrollView.scrollIndicators.vertical?.backgroundColor = UIColor.yourcolor
        }
    }
    

    You will access to the first view and change the color properly:

    Kudos to @Alex who posted a great solution

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