Swift iOS - 如果CollectionView中没有任何单元格,如何将Sticky Header滚动到屏幕顶部?

时间:2018-04-17 23:07:35

标签: ios swift scroll uicollectionview

仅供参考,当用户向上滑动以查看更多单元格时,此问题适用于手动滚动。

我跟着this tutorial并制作了一个标题。

一切正常,当CollectionView内部有足够的单元格来填充整个屏幕(假设50个或更多单元格)时,粘贴标题会滚动到导航栏下方的屏幕顶部。

Sticky Header Scroll to top of screen since there are cells

问题是当CollectionView中没有任何单元格或者单元格数小于屏幕高度(即1或2个单元格)时,粘性标题将不会滚动到导航栏下方的屏幕顶部。它保持不变。

Sticky Header won't scroll to the top of screen since there aren't any class inside of it.

当内部没有任何单元格或者单元格数量少于屏幕高度时,如何让粘贴标题滚动到导航栏下方场景的顶部?

Sticky Header stills scroll to the top screen even though there aren't any cells inside of it

以下代码:

这是针对粘性标题上方的白色单元格,当粘性标题滚动到顶部时,它将在屏幕外滚动:

class WhiteCellAboveStickyHeader: UICollectionViewCell{

    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = .white

        // height is configured to 200 inside the collectionView's sizeForItemAt IndexPath
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

这是针对粘性标题下方的单元格,当有足够的单元格时,它会滚动到屏幕顶部:

class BlueCellBelowStickyHeader: UICollectionViewCell{

    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = .blue

        // height is configured to 50 inside the collectionView's sizeForItemAt IndexPath
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

这是粘性标题的headerView:

class StickyHeader: UICollectionReusableView {

    let header: UIView = {
        let header = UIView()
        header.translatesAutoresizingMaskIntoConstraints = false
        return header
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)

        backgroundColor = .orange

        addSubview(header)
        header.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 0).isActive = true
        header.rightAnchor.constraint(equalTo: self.rightAnchor, constant: 0).isActive = true
        header.topAnchor.constraint(equalTo: self.topAnchor, constant: 8).isActive = true
        header.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: 0).isActive = true
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

使用CollectionView的类:

class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {

var collectionView: UICollectionView!
let whiteCellAboveStickyHeader = "WhiteCellAboveStickyHeader"
let blueCellBelowStickyHeader = "BlueCellBelowStickyHeader"
let stickyHeader = "StickyHeader"

override func viewDidLoad() {
    super.viewDidLoad()

    view.backgroundColor = .white
    navigationItem.title = "Nav Bar"

    let layout = UICollectionViewFlowLayout()
    layout.sectionInset = UIEdgeInsetsMake(0, 0, 0, 0)

    collectionView = UICollectionView(frame: CGRect.zero, collectionViewLayout: layout)
    collectionView.translatesAutoresizingMaskIntoConstraints = false
    collectionView.dataSource = self
    collectionView.delegate = self
    collectionView.backgroundColor = .white
    collectionView.alwaysBounceVertical = true
    collectionView.showsVerticalScrollIndicator = false
    collectionView.register(WhiteCellAboveStickyHeader.self, forCellWithReuseIdentifier: whiteCellAboveStickyHeader)
    collectionView.register(BlueCellBelowStickyHeader.self, forCellWithReuseIdentifier: blueCellBelowStickyHeader)
    collectionView.register(StickyHeader.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: stickyHeader)
    view.addSubview(collectionView)

    collectionView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor).isActive = true
    collectionView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor).isActive = true
    collectionView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
    collectionView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true

    // These 2 lines are what makes the sticky header sticky
    let stickyHeaderLayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout
    stickyHeaderLayout?.sectionHeadersPinToVisibleBounds = true
}

func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 2
}

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {

        // this is for the white cell above the sticky header
        if section == 0 {
            return 1
        }

        /*
         -this is for the blue cell below the sticky header
         -since there aren't any cells underneath the sticky header it won't scroll to the top of the screen
         -if this number is 50 it will scroll to the top
        */
        return 0
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

        // this is for the white cell above the sticky header
        if indexPath.section == 0 {

            let whiteCell = collectionView.dequeueReusableCell(withReuseIdentifier: whiteCellAboveStickyHeader, for: indexPath) as! WhiteCellAboveStickyHeader
            return whiteCell
        }

        //  this is for the blue cell below the sticky header
        let blueCell = collectionView.dequeueReusableCell(withReuseIdentifier: blueCellBelowStickyHeader, for: indexPath)  as! BlueCellBelowStickyHeader
        return blueCell
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

    // this is for the white cell above the sticky header
    if indexPath.section == 0{
        return CGSize(width: view.frame.size.width, height: 200)
    }

    // this is for the blue cells underneath the sticky header
    return CGSize(width: view.frame.size.width, height: 50)
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {

    // this is for the cell above the sticky header
    if section == 0{
        return 0
    }

    // this is for the spacing between blue cells underneath the sticky header
    return 10
}

func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView{

        // since only 1 section will have a header in it then only return this

        var header: UICollectionReusableView?

        if kind == UICollectionElementKindSectionHeader{

            header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: self.stickyHeader, for: indexPath) as! StickyHeader
        }

        return header!
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {

        // if section is above sticky header make its height 0 so there won't be a header
        if section == 0 {
            return CGSize(width: 0, height: 0)
        }

        // for section header which is the StickyHeader configure it's height
        return CGSize(width: collectionView.frame.width, height: 100)
}

}

的AppDelegate:

class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?


    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

        window = UIWindow(frame: UIScreen.main.bounds)
        window?.makeKeyAndVisible()

        UINavigationBar.appearance().barTintColor = UIColor.lightGray
        UINavigationBar.appearance().tintColor = UIColor.black
        UINavigationBar.appearance().titleTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.black]

        let navVC = UINavigationController(rootViewController: ViewController())
        window?.rootViewController = navVC

        return true
    }

...

0 个答案:

没有答案