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

后端 未结 11 1554
遇见更好的自我
遇见更好的自我 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 03:35
     scrollView.scrollRectToVisible(CGRect(x: x, y: y, width: 1, height:
    1), animated: true)
    

    or

    scrollView.setContentOffset(CGPoint(x: x, y: y), animated: true)
    

    Another way is

    scrollView.contentOffset = CGPointMake(x,y);
    

    and i do it with animated like this

    [UIView animateWithDuration:2.0f delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
    scrollView.contentOffset = CGPointMake(x, y); }
    completion:NULL];
    
    0 讨论(0)
  • 2020-12-29 03:36

    For scroll to top or bottom with completion of the animation

    // MARK: - UIScrollView extensions
    
    extension UIScrollView {
        /// Animate scroll to bottom with completion
        ///
        /// - Parameters:
        ///   - duration:   TimeInterval
        ///   - completion: Completion block
        func animateScrollToBottom(withDuration duration:  TimeInterval,
                                completion:             (()->())? = nil) {
    
            UIView.animate(withDuration: duration, animations: { [weak self] in
                self?.setContentOffset(CGPoint.zero, animated: false)
                }, completion: { finish in
                    if finish { completion?() }
            })
        }
    
        /// Animate scroll to top with completion
        ///
        /// - Parameters:
        ///   - duration:   TimeInterval
        ///   - completion: Completion block
        func animateScrollToBottomTop(withDuration duration:  TimeInterval,
                                      completion:             (()->())? = nil) {
            UIView.animate(withDuration: duration, animations: { [weak self] in
                guard let `self` = self else {
                    return
                }
                let desiredOffset = CGPoint(x: 0, y: -self.contentInset.top)
                self.setContentOffset(desiredOffset, animated: false)
    
                }, completion: { finish in
                    if finish { completion?() }
            })
        }
    }
    
    0 讨论(0)
  • 2020-12-29 03:43
    scrollView.setContentOffset(CGPoint, animated: Bool)
    

    Where the point's y coordinate is the y coordinate of the frame of the view you want to show relatively to the scrollView's content view.

    0 讨论(0)
  • 2020-12-29 03:43

    Here is my answer, this is in swift. This will scroll the pages in scrollview infinitely.

    private func startBannerSlideShow()
    {
    UIView.animate(withDuration: 6, delay: 0.1, options: .allowUserInteraction, animations: {
        scrollviewOutlt.contentOffset.x = (scrollviewOutlt.contentOffset.x == scrollviewOutlt.bounds.width*2) ? 0 : scrollviewOutlt.contentOffset.x+scrollviewOutlt.bounds.width
    }, completion: { (status) in
        self.startBannerSlideShow()
    })
    }
    
    0 讨论(0)
  • 2020-12-29 03:44

    For me, the thing was the navigation bar which overlapped the small portion of the scrollView content. So I've made 2 things:

    • Size Inspector - Scroll View - Content Insets --> Change from Automatic to Never.
    • Size Inspector - Constraints- "Align Top to" (Top Alignment Constraints)- Second item --> Change from Superview.Top to Safe Area.Top and the value(constant field) set to 0

    0 讨论(0)
  • 2020-12-29 03:49

    For me scrollRectToVisible() didn't work (see here), so I used setContentOffset() and calculated it myself, based on AMAN77's answer:

    extension UIScrollView {
    
        func scrollToView(view:UIView, animated: Bool) {
            if let superview = view.superview {
                let child = superview.convert(view.frame, to: self)
                let visible = CGRect(origin: contentOffset, size: visibleSize)
                let newOffsetY = child.minY < visible.minY ? child.minY : child.maxY > visible.maxY ? child.maxY - visible.height : nil
                if let y = newOffsetY {
                    setContentOffset(CGPoint(x:0, y: y), animated: animated)
                }
            }
        }
    
    }
    

    It is for a horizontal scroll view, but the same idea can be applied vertically too.

    0 讨论(0)
提交回复
热议问题