【问题标题】:CollectionView -Stop/Prevent Section Header from Scrolling Beyond a Certain PointCollectionView - 停止/防止部分标题滚动超出某个点
【发布时间】:2021-10-05 03:30:39
【问题描述】:

我有一个 collectionView,它固定在视图控制器的顶部,没有导航栏 collectionView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true

它有一个粘性标题let headerLayout = cv.collectionViewLayout as? UICollectionViewFlowLayout; headerLayout?.sectionHeadersPinToVisibleBounds = true

collectionView 有 2 个部分,第一个部分没有标题,但第二个部分有标题。问题是因为 collectionView 没有固定到 safeAreaLayoutGuide.topAnchor 并且没有导航栏,当我滚动时,第二部分中的标题被固定到状态栏后面的屏幕顶部。

如何防止标题滚动到某个点之外。例如,如果我将一个按钮固定在屏幕顶部,则标题会在它碰到按钮底部时停止

myButton.topAnchor.constraint(equalTo: view.topAnchor, constant: 50).isActive = true

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    scrollView.contentInsetAdjustmentBehavior = .never

    let secondIndexPath = IndexPath(item: 0, section: 1)

    collectionView.layoutIfNeeded()
    if let headerFrameInCollectionView = collectionView.layoutAttributesForSupplementaryElement(ofKind: UICollectionView.elementKindSectionHeader, at: secondIndexPath), let window = UIApplication.shared.windows.first(where: \.isKeyWindow) {

        let headerFrameInSuperView = collectionView.convert(headerFrameInCollectionView.frame, to: collectionView.superview)
        let headerOriginY = headerFrameInSuperView.origin.y

        let buttonFrame = view.convert(myButton.frame, to: window)

        let bottomOfButton = buttonFrame.origin.y + buttonFrame.height

        if headerOriginY == bottomOfButton {

            collectionView.contentInset.top = headerOriginY // stop header from scrolling any further

        } else {

            collectionView.contentInset.top = 0
        }
    }
}

【问题讨论】:

    标签: ios swift uicollectionview uiscrollview


    【解决方案1】:

    简而言之,要使其工作,我必须将collectionView.contentInset.top 设置为我希望第二节的标题停止的任何点,但我还必须将collectionView.contentOffset.y 设置为停止位置。

    if headerOriginY <= bottomOfButton {
    
        collectionView.contentInset.top = bottomOfButton
    
        collectionView.contentOffset.y = cellHeightFromSectionOne - bottomOfButton
    
    } else {
    
        collectionView.contentInset.top = 0
    }
    

    总之,我有 2 个部分,如果我在第 2 部分中设置 collectionView.contentInset.top = bottomOfButton 而不更改 collectionView.contentOffset.y,则第 1 部分中的单元格会滚动到屏幕外,整个过程非常错误。让它工作:

    1- 获取第一部分中单元格的高度。幸运的是,这很容易,因为在第 1 节中,单元格的高度是屏幕的宽度,第 1 节中只有 1 个单元格。在第 2 节中没有任何单元格,因此单元格大小为 .zero:

    // size for the cells
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    
        let width = UIScreen.main.bounds.width // the collectionView is the same width
    
        if indexPath.section == 0 {
    
            return CGSize(width: width, height: width)
        }
    
        return .zero // section 2 has no cells, just a header
    }
    

    2- 在scrollViewDidScroll 中,所有工作都在这里完成。变量名说明过程

    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        scrollView.contentInsetAdjustmentBehavior = .never
    
        let secondIndexPath = IndexPath(item: 0, section: 1)
    
        collectionView.layoutIfNeeded()
    
        if let headerTwoAttributes = collectionView.layoutAttributesForSupplementaryElement(ofKind: UICollectionView.elementKindSectionHeader, at: secondIndexPath), let window = UIApplication.shared.windows.first(where: \.isKeyWindow) {
    
            let headerTwoFrameInSuperView = collectionView.convert(headerTwoAttributes.frame, to: collectionView.superview)
    
            let headerTwoOriginY = headerTwoFrameInSuperView.origin.y
    
            let buttonFrame = view.convert(myButton.frame, to: window)
    
            let bottomPositionOfButtonInWindow = buttonFrame.origin.y + buttonFrame.height
    
            let stopScrollingPositionY = bottomPositionOfButtonInWindow
    
            let cellHeightFromSectionOne = UIScreen.main.bounds.width
    
            let preventFirstCellInSectionOneFromScrollingPosition = cellHeightFromSectionOne - stopScrollingPositionY
    
            if headerTwoOriginY <= stopScrollingPositionY {
    
                collectionView.contentInset.top = stopScrollingPositionY
                        
                collectionView.contentOffset.y = preventFirstCellInSectionOneFromScrollingPosition
    
            } else {
    
                collectionView.contentInset.top = 0 // reset this to 0
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-31
      • 1970-01-01
      • 2011-08-19
      • 1970-01-01
      相关资源
      最近更新 更多