Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to access scrollbar position in swift

I'm trying to access the position of a scrollbar in scrollview so that I can attach some UI elements to it. The only method I've found to access this is scrollViewDidScroll(_ scrollView:).

This gives me the scrollView.contentOffset.y property, but I can't seem to use it during runtime to attach my UI to it. I think this gives me the entire scrollview length though, and not the position of the scrollbar.

I'm basically trying to do exactly what's circled in red in this screenshot. (KakaoTalk message)

enter image description here

like image 236
Tim Isenman Avatar asked Oct 21 '25 02:10

Tim Isenman


1 Answers

The simplest way I've found to get the relative position of the scrollBar position is to find it's current percentage in the scrollView, and use that value to find the percent the scrollBar is at within the Bounds.

ScrollView position: (scrollView.contentOffset.y / scrollView.contentSize.height)

Which is basically Current Scrolling Position / Total Height of ScrollView

Let's call it scrollPercent.

let scrollPercent = (scrollView.contentOffset.y / scrollView.contentSize.height)

That will give you a % value between 0 and 1 (0% and 100%).

You can take the the scrollPercent and multiply it by the Parent View's max height view.bounds.size.height, to get the approximate Y value of the scrollbar within the view.

let scrollBarPosition = scrollPercent * (view.bounds.size.height)

This can be used as the Y value for your UI element.

When you are doing this, be sure to check that scrollView.contentSize.height is > 0, because it starts as zero, and if you try to divide by that, the number will reach infinite and your app will crash.

The final solution looks like this:

func scrollViewDidScroll(_ scrollView: UIScrollView) {

    let scrollBarPosition: CGFloat = (scrollView.contentOffset.y / scrollView.contentSize.height) * (view.bounds.size.height)

    if scrollView.contentSize.height > 0 {
        dateScrollbar.snp.remakeConstraints { (make) in
            make.centerY.equalTo(scrollBarPosition)
            make.trailing.equalToSuperview().inset(110)
        }

    }
}

Note: I am using an autolayout library called SnapKit for setting autolayout constraints.

EDIT: The above solution works, but it will also extend your new UI off-screen at the top and bottom of your scrollView.

To fix this: Add a subview to the parentView, and make the subView's height the denominator of the scrollBarPosition. This will act like a "track" for any UI like the picture to slide against, and stay within its bounds.

let scrollBarTrack = UIView()
view.addSubView(scrollBarTrack)
//Put it wherever you want, with the height being equal to whatever you want, and the width can be something like 1.

and then update your scrollBarPosition

let scrollBarPosition = scrollPercent * (scrollBarTrack.bounds.size.height)

It should stay within whatever those bounds are :)

like image 150
Tim Isenman Avatar answered Oct 23 '25 17:10

Tim Isenman



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!