Reputation: 3202
I have UIScrollview
that the user scrolls up and down.
Is there a way to adjust how much the user's drag of the finger results in the final scroll amount?
I was looking at UIScrollview delegate methods, but haven't found a place to alter that.
scrollViewDidScroll(_:)
seems too late since this is AFTER the event.
Upvotes: 0
Views: 53
Reputation: 77690
iOS users are very familiar with using scrolling views, so changing the "scroll speed" may be confusing. However, it's your app :)
Give this a try...
When the user Begins dragging, we'll grab the .contentOffset.y
as a "starting point." In scrollViewDidScroll
, we'll get the difference between the new .contentOffset.y
and the startingY
... multiply that by the speed factor ... and then change the .contentOffset.y
.
Note that manually setting .contentOffset.y
triggers scrollViewDidScroll
, so we'll also need to set a bool flag to prevent recursion:
class SlowScrollVC: UIViewController, UIScrollViewDelegate {
// scrollSpeed --- example values
// 1.0 == normal
// 1.5 == fast
// 0.5 == slow
var scrollSpeed: CGFloat = 0.5
var startingOffsetY: CGFloat = 0
var bManualOffset: Bool = false
let scrollView = UIScrollView()
override func viewDidLoad() {
super.viewDidLoad()
// add a bunch of labels and buttons so we have something to scroll
let stack = UIStackView()
stack.axis = .vertical
stack.spacing = 40
for i in 1...20 {
let v = UILabel()
v.text = "Label \(i)"
v.textAlignment = .center
v.backgroundColor = .cyan
stack.addArrangedSubview(v)
let b = UIButton()
b.setTitle("Button \(i)", for: [])
b.setTitleColor(.white, for: .normal)
b.setTitleColor(.lightGray, for: .highlighted)
b.backgroundColor = .systemBlue
b.addTarget(self, action: #selector(btnTap(_:)), for: .touchUpInside)
stack.addArrangedSubview(b)
}
stack.translatesAutoresizingMaskIntoConstraints = false
scrollView.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(stack)
view.addSubview(scrollView)
// so we can see the scroll view frame
scrollView.backgroundColor = .yellow
let g = view.safeAreaLayoutGuide
let cg = scrollView.contentLayoutGuide
let fg = scrollView.frameLayoutGuide
NSLayoutConstraint.activate([
scrollView.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
scrollView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
scrollView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
scrollView.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: -20.0),
stack.topAnchor.constraint(equalTo: cg.topAnchor, constant: 8.0),
stack.leadingAnchor.constraint(equalTo: cg.leadingAnchor, constant: 8.0),
stack.trailingAnchor.constraint(equalTo: cg.trailingAnchor, constant: -8.0),
stack.bottomAnchor.constraint(equalTo: cg.bottomAnchor, constant: -8.0),
stack.widthAnchor.constraint(equalTo: fg.widthAnchor, constant: -16.0),
])
scrollView.delegate = self
// you may also want to adjust .decelerationRate
// try various values to see the result
//scrollView.decelerationRate = UIScrollView.DecelerationRate(rawValue: 0.99)
}
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
startingOffsetY = scrollView.contentOffset.y
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if !bManualOffset {
// get the difference between previous offset.y and new offset.y
let diff = scrollView.contentOffset.y - startingOffsetY
// adjust by scroll-speed factor
let newY = startingOffsetY + diff * scrollSpeed
// prevent recursion
bManualOffset = true
// set adjusted offset.y
scrollView.contentOffset.y = newY
// update start Y
startingOffsetY = newY
}
bManualOffset = false
}
@objc func btnTap(_ sender: UIButton) {
// just to confirm we tapped a button
print("Tap:", sender.currentTitle)
}
}
Upvotes: 1