Using the scroll position, we can do this by comparing previous and current positions, but I wanted to make it simple as the drag velocity instantly changes when the direction of the swipe changes, and there is no need to have previous values as well. Also, in SwiftUI, there is no way to directly read scroll positions, and we can use Preference keys, but use of those inside Lazy Stacks results in unpredicted offsets since the layout changes when the content goes outside the visible region.
Hi, I just noticed that the UUID used on the gesture ID is updating when scrolling, which in terms adds multiple gestures to the view, so simply change the UUID().uuidString to “CUSTOMGESTRUE”.
I think you can avoid using pan gesture and use only a scroll position observer to check if is going down or up. Thanks for your amazing work
Which one is better?
Using the scroll position, we can do this by comparing previous and current positions, but I wanted to make it simple as the drag velocity instantly changes when the direction of the swipe changes, and there is no need to have previous values as well. Also, in SwiftUI, there is no way to directly read scroll positions, and we can use Preference keys, but use of those inside Lazy Stacks results in unpredicted offsets since the layout changes when the content goes outside the visible region.
Thank you! I'm able to follow your video and it works but man how you achieve this knowledge originally? Bravo!
Excellent improvement 👋
can you hide the nav bar with this same set up? similar to new twitter
Possible to do the same in UIKit?
the performance of the ScrollView is really bad when I add the panGesture !
Hi, I just noticed that the UUID used on the gesture ID is updating when scrolling, which in terms adds multiple gestures to the view, so simply change the UUID().uuidString to “CUSTOMGESTRUE”.
hi
Brooo, i've been waiting for this
struct ProductsScrollDirectionCustomGesture: UIViewRepresentable {
// MARK: - Nested Types
typealias GestureHandler = (UIPanGestureRecognizer) -> Void
class Coordinator: NSObject, UIGestureRecognizerDelegate {
// MARK: - Properties
var onChange: GestureHandler
// MARK: - Init
init(onChange: @escaping GestureHandler) {
self.onChange = onChange
}
// MARK: - Functions
@objc
func gestureChange(gesture: UIPanGestureRecognizer) {
onChange(gesture)
}
func gestureRecognizer(
_ gestureRecognizer: UIGestureRecognizer,
shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer
) -> Bool {
true
}
}
// MARK: - Properties
var onChange: GestureHandler
private let gestureId = UUID().uuidString
// MARK: - Functions
func makeCoordinator() -> Coordinator {
Coordinator(onChange: onChange)
}
func makeUIView(context: Context) -> some UIView {
UIView()
}
func updateUIView(_ uiView: UIViewType, context: Context) {
DispatchQueue.main.async {
guard
let superview = uiView.superview?.superview,
!(superview.gestureRecognizers?.contains(where: { $0.name == gestureId }) ?? false) else { return }
let gesture = UIPanGestureRecognizer(
target: context.coordinator,
action: #selector(context.coordinator.gestureChange(gesture:))
)
gesture.name = gestureId
gesture.delegate = context.coordinator
superview.addGestureRecognizer(gesture)
}
}
}