仅供参考,当用户向上滑动以查看更多单元格时,此问题适用于手动滚动。
我跟着this tutorial并制作了一个标题。
一切正常,当CollectionView内部有足够的单元格来填充整个屏幕(假设50个或更多单元格)时,粘贴标题会滚动到导航栏下方的屏幕顶部。
问题是当CollectionView中没有任何单元格或者单元格数小于屏幕高度(即1或2个单元格)时,粘性标题将不会滚动到导航栏下方的屏幕顶部。它保持不变。
当内部没有任何单元格或者单元格数量少于屏幕高度时,如何让粘贴标题滚动到导航栏下方场景的顶部?
以下代码:
这是针对粘性标题上方的白色单元格,当粘性标题滚动到顶部时,它将在屏幕外滚动:
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
}
...