检测ScrollView滚动至边界时的拖拽方向,实现垂直ScrollView视图显隐控制
Hey there! Let's work through your two iOS ScrollView requirements with practical, actionable code and explanations.
1. Detect Drag Direction When Scrolling Beyond ScrollView Bounds
To catch the drag direction when hitting the ScrollView's edges, we can leverage the ScrollView's built-in panGestureRecognizer to track touch movement, paired with checks for boundary conditions. Here's how to implement it:
Implementation Steps:
- Hook into the pan gesture's state changes to track real-time movement
- Use the gesture's translation value to determine drag direction (positive Y = down, negative Y = up)
- Combine this with checks for whether the ScrollView is at its top or bottom boundary
class ScrollHandlerViewController: UIViewController, UIScrollViewDelegate { @IBOutlet weak var mainScrollView: UIScrollView! override func viewDidLoad() { super.viewDidLoad() mainScrollView.delegate = self // Attach a handler to the ScrollView's pan gesture mainScrollView.panGestureRecognizer.addTarget(self, action: #selector(handleEdgeDrag(_:))) } @objc private func handleEdgeDrag(_ gesture: UIPanGestureRecognizer) { // Only process changes in gesture state guard gesture.state == .changed else { return } let dragTranslation = gesture.translation(in: mainScrollView) let isAtTop = mainScrollView.contentOffset.y <= 0 let isAtBottom = mainScrollView.contentOffset.y >= (mainScrollView.contentSize.height - mainScrollView.bounds.height) // Check drag direction + boundary condition if dragTranslation.y > 0 { if isAtTop { print("*Dragging down while pinned to top boundary*") // Add your top-edge down-drag logic here } } else if dragTranslation.y < 0 { if isAtBottom { print("*Dragging up while pinned to bottom boundary*") // Add your bottom-edge up-drag logic here } } // Reset translation to avoid cumulative offset affecting future checks gesture.setTranslation(.zero, in: mainScrollView) } }
Key Notes:
- Resetting the gesture's translation ensures we only get the incremental movement each time, instead of a cumulative value that would skew direction checks.
- The boundary checks use
contentOffsetandcontentSizeto confirm we're truly at the edge of the scrollable content.
2. Hide Window-Added View Based on Specific Scroll Behaviors
For your vertical ScrollView with two screen-sized containers, we need to hide a window-level View when scrolling down, but keep it visible if we're at the top (contentOffset.y = 0) and dragging up (where the offset stays at 0). Here's a robust solution:
Implementation Steps:
- Track the previous scroll offset to determine scroll direction
- Use
scrollViewDidScrollto react to real-time scroll changes - Animate the window View's visibility based on scroll direction and boundary state
class ScrollViewVisibilityController: UIViewController, UIScrollViewDelegate { @IBOutlet weak var mainScrollView: UIScrollView! // Example window-level View (adjust frame/properties to match your use case) private let floatingWindowView: UIView = { let view = UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 64)) view.backgroundColor = .systemBlue view.autoresizingMask = [.flexibleWidth] return view }() private var lastScrollOffsetY: CGFloat = 0 override func viewDidLoad() { super.viewDidLoad() mainScrollView.delegate = self // Set content size to fit two screen-height containers mainScrollView.contentSize = CGSize(width: view.bounds.width, height: view.bounds.height * 2) // Add the View to the app's main window if let mainWindow = UIApplication.shared.windows.first { mainWindow.addSubview(floatingWindowView) } } func scrollViewDidScroll(_ scrollView: UIScrollView) { let currentOffsetY = scrollView.contentOffset.y let isScrollingDown = currentOffsetY > lastScrollOffsetY let isAtTop = currentOffsetY <= 0 if isScrollingDown { // Animate window View off-screen when scrolling down UIView.animate(withDuration: 0.3, delay: 0, options: .curveEaseInOut) { self.floatingWindowView.transform = CGAffineTransform(translationX: 0, y: -self.floatingWindowView.bounds.height) } } else { // Handle upward scrolling if isAtTop { // Keep window View visible when dragging up from the top UIView.animate(withDuration: 0.3, delay: 0, options: .curveEaseInOut) { self.floatingWindowView.transform = .identity } } else { // Show window View when scrolling up from non-top positions UIView.animate(withDuration: 0.3, delay: 0, options: .curveEaseInOut) { self.floatingWindowView.transform = .identity } } } // Update last offset for next scroll check lastScrollOffsetY = currentOffsetY } // Ensure window View is visible if scroll ends at the top func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { if scrollView.contentOffset.y <= 0 { UIView.animate(withDuration: 0.3) { self.floatingWindowView.transform = .identity } } } }
Key Notes:
- Using
lastScrollOffsetYlets us reliably detect scroll direction by comparing the current and previous positions. - The animation uses
CGAffineTransformto slide the View off-screen smoothly, which is more performant than modifying the frame directly. - The
scrollViewDidEndDeceleratingmethod acts as a safety net to ensure the View is visible if the scroll stops at the top.
内容的提问来源于stack exchange,提问作者pravir
相关产品推荐
相关产品推荐

