Programmatically scroll a UIScrollView to the top of a child UIView (subview) in Swift

后端 未结 11 1598
遇见更好的自我
遇见更好的自我 2020-12-29 03:35

I have a few screens worth of content within my UIScrollView which only scrolls vertically.

I want to programmatically scroll to a view contained somewhere in it\'s

11条回答
  •  [愿得一人]
    2020-12-29 04:00

    Updated dyson's answer to behave like UITableView's scrollToRowAtIndexPath:atScrollPosition:animated: since that was my use case:

    extension UIScrollView {
        
        /// Scrolls to a subview of the current `UIScrollView `.
        /// - Parameters:
        ///   - view: The subview  to which it should scroll to.
        ///   - position: A constant that identifies a relative position in the `UIScrollView ` (top, middle, bottom) for the subview when scrolling concludes. See UITableViewScrollPosition for descriptions of valid constants.
        ///   - animated: `true` if you want to animate the change in position; `false` if it should be immediate.
        func scrollToView(view: UIView,
                          position: UITableView.ScrollPosition = .top,
                          animated: Bool) {
            
            // Position 'None' should not scroll view to top if visible like in UITableView
            if position == .none &&
                bounds.intersects(view.frame) {
                return
            }
            
            if let origin = view.superview {
                // Get the subview's start point relative to the current UIScrollView
                let childStartPoint = origin.convert(view.frame.origin,
                                                     to: self)
                var scrollPointY: CGFloat
                switch position {
                case .bottom:
                    let childEndY = childStartPoint.y + view.frame.height
                    scrollPointY = CGFloat.maximum(childEndY - frame.size.height, 0)
                case .middle:
                    let childCenterY = childStartPoint.y + view.frame.height / 2.0
                    let scrollViewCenterY = frame.size.height / 2.0
                    scrollPointY = CGFloat.maximum(childCenterY - scrollViewCenterY, 0)
                default:
                    // Scroll to top
                    scrollPointY = childStartPoint.y
                }
    
                // Scroll to the calculated Y point
                scrollRectToVisible(CGRect(x: 0,
                                           y: scrollPointY,
                                           width: 1,
                                           height: frame.height),
                                    animated: animated)
            }
        }
    
        
        /// Scrolls to the top of the current `UIScrollView`.
        /// - Parameter animated: `true` if you want to animate the change in position; `false` if it should be immediate.
        func scrollToTop(animated: Bool) {
            let topOffset = CGPoint(x: 0, y: -contentInset.top)
            setContentOffset(topOffset, animated: animated)
        }
    
        /// Scrolls to the bottom of the current `UIScrollView`.
        /// - Parameter animated: `true` if you want to animate the change in position; `false` if it should be immediate.
        func scrollToBottom(animated: Bool) {
            let bottomOffset = CGPoint(x: 0,
                                       y: contentSize.height - bounds.size.height + contentInset.bottom)
            if (bottomOffset.y > 0) {
                setContentOffset(bottomOffset, animated: animated)
            }
        }
    }
    

提交回复
热议问题