ios 回调到sectionHeadersPinToVisibleBounds

ktecyv1j  于 2023-05-19  发布在  iOS
关注(0)|答案(2)|浏览(204)

我在我的项目中有一个要求,当UICollectionView头变得粘滞时,我必须向它们添加阴影。
我正在使用UICollectionViewFlowLayout节HeadersPinToVisibleBounds上的属性,当设置为YES时,它会使标题具有粘性。
当标题变得粘滞并实际固定到顶部时,我们是否可以获得某种回调,以便我可以向该标题添加阴影?我不希望当一个头不粘的时候有阴影。
这里的挑战是,我不能真正利用method- layoutAttributesForSupplementaryView中的信息:它确实为我提供了屏幕上的视图,因为我的部分具有动态的项目数,因此屏幕上的哪个部分并没有真正告诉我谁需要阴影。

goucqfw6

goucqfw61#

我通过以下方法找到了这个问题的答案:
1.手动保存表头位置:

func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { 
let cell = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "CategoryNameReusableView", for: indexPath) as! CategoryNameReusableView
            cell.nameLbl.text = sectionNames[indexPath.section]
            if viewWithPosition.isEmpty { viewWithPosition.append(( name: cell.nameLbl.text!, position: cell.frame.origin.y))}
            let x = isElementInArray(array: viewWithPosition, string: cell.nameLbl.text!)
            if !x {
                viewWithPosition.append((name: cell.nameLbl.text!, position: cell.frame.origin.y))
            }
        return cell
}

我使用的是viewWithPosition元组var viewWithPosition = [(name: String, position: CGFloat)]()的数组。如果我只保存单元格的位置,情况可能是一样的,但由于我的单元格有不同的文本,我使用name参数来检查元素是否已经存在于数组中。我使用了helper函数:

fileprivate func isElementInArray(array: [ViewAndPosition], string: String) -> Bool {
    var bool = false
    for views in array {
        if views.name == string {
            bool = true
            return bool
        }
    }
    return bool
}

1.当我有初始位置时,我检查可见标题是否放错了位置:

func scrollViewDidScroll(_ scrollView: UIScrollView) {
if let visibleHeadersInSection = collectionView.visibleSupplementaryViews(ofKind: UICollectionElementKindSectionHeader) as? [CategoryNameReusableView] {
    for header in visibleHeadersInSection{
        if let index = viewWithPosition.index(where: { (element) -> Bool in
            element.name == header.nameLbl.text
        }){
            if header.frame.origin.y == viewWithPosition[index].position {
                header.backgroundColor = UIColor.clear
            } else {
                header.backgroundColor = UIColor.white
            }
        }
    }
}

}
目前,苹果似乎没有为这种情况提供任何回调。希望这也是你的解决方案。

dw1jzc5e

dw1jzc5e2#

我对IvanMih的解决方案进行了现代化和改进。请注意,headerGroupsBeingDisplayed是在UICollectionView中显示的数据集:

// Array of tuples that stores data about all inflated headers. Used for conditionally changing sticky header color.
// The "position" is the original vertical position of the header view relative to its frame. When a header sticks to the top, the header view is no longer aligned with its frame.
// We exploit this lack of alignment to detect when a given header is stuck to the top.
var headerStringsAndOriginalPositions = [(name: String, position: CGFloat)]()

// Specify how Header views get inflated. Add a header to headerStringsAndOriginalPositions if not already present.
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
    let cell = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "DateHeaderReusableView", for: indexPath) as! DateHeaderReusableView
    let dateHeaderString = headerGroupsBeingDisplayed[indexPath.section].dateHeader
    cell.dateLabel.text = dateHeaderString
    if (!headerStringsAndOriginalPositions.contains(where: { name, position in name == dateHeaderString })) {
        headerStringsAndOriginalPositions.append((name: dateHeaderString, position: cell.frame.origin.y))
    }
    return cell
}

// Every time user scrolls, iterate through list of visible headers and check whether they're sticky or not. Then modify the header views accordingly.
func scrollViewDidScroll(_ scrollView: UIScrollView) {
    if let visibleHeadersInSection = collectionView.visibleSupplementaryViews(ofKind: UICollectionView.elementKindSectionHeader) as? [DateHeaderReusableView] {
        for header in visibleHeadersInSection {
            if let index = headerStringsAndOriginalPositions.firstIndex(where: { (element) -> Bool in element.name == header.dateLabel.text }) {
                if (header.frame.origin.y == headerStringsAndOriginalPositions[index].position) {
                    // Header is non-sticky (as header view is aligned with its frame).
                    header.dateLabel.textColor = .red
                } else {
                    // Header is sticky (as header view is not aligned with its frame).
                    header.dateLabel.textColor = .blue
                }
            }
        }
    }
}

相关问题