根据之前的 cmets - 这似乎是 ios 10.3 的错误
当您使用 uicollectionview - 我提请您注意我从 APDynamicHeaderTableViewController 重新编写的一些代码
https://github.com/aaronpang/APDynamicHeaderTableViewController/issues/4
它正在使用 snapkit https://github.com/SnapKit/SnapKit
(向所有 IB + NSLayout 约束爱好者道歉。)
class APDynamicHeaderTableViewController : UIViewController {
var largeWideSize = CGSize(width: UIScreen.main.bounds.width , height: 285 )
let headerView = APDynamicHeaderView () // Change your header view here
let cellLayout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
var feedCV:UICollectionView!
fileprivate var headerViewHeight:CGFloat = 80 // this will be updated by scrolling
fileprivate var headerBeganCollapsed = false
fileprivate var collapsedHeaderViewHeight : CGFloat = UIApplication.shared.statusBarFrame.height
fileprivate var expandedHeaderViewHeight : CGFloat = 100
fileprivate var headerExpandDelay : CGFloat = 100
fileprivate var tableViewScrollOffsetBeginDraggingY : CGFloat = 0.0
init(collapsedHeaderViewHeight : CGFloat, expandedHeaderViewHeight : CGFloat, headerExpandDelay :CGFloat) {
self.collapsedHeaderViewHeight = collapsedHeaderViewHeight
self.expandedHeaderViewHeight = expandedHeaderViewHeight
self.headerExpandDelay = headerExpandDelay
super.init(nibName: nil, bundle: nil)
}
init () {
super.init(nibName: nil, bundle: nil)
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func loadView() {
super.loadView()
self.view.backgroundColor = .green
// Cell Layout Sizes
cellLayout.scrollDirection = .vertical
cellLayout.sectionInset = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 10)
cellLayout.itemSize = CGSize(width: UIScreen.main.bounds.width, height: 185 + 80)
// Header view
self.view.addSubview(headerView)
headerView.snp.remakeConstraints { (make) -> Void in
make.top.left.equalToSuperview()
make.width.equalToSuperview()
make.height.equalTo(headerViewHeight)
}
// CollectionView
feedCV = UICollectionView(frame: .zero, collectionViewLayout: cellLayout)
self.view.addSubview(feedCV)
self.feedCV.snp.remakeConstraints { (make) -> Void in
make.top.equalTo(headerView.snp.bottom) // this is pegged to the header view which is going to grow in height
make.left.equalToSuperview()
make.width.equalToSuperview()
make.bottom.equalToSuperview()
}
feedCV.backgroundColor = .red
feedCV.showsVerticalScrollIndicator = true
feedCV.isScrollEnabled = true
feedCV.bounces = true
feedCV.delegate = self
feedCV.dataSource = self
// YOUR COLLECTIONVIEW CELL HERE!!!!!
feedCV.register(VideoCollectionViewCell.self, forCellWithReuseIdentifier: VideoCollectionViewCell.ID)
}
// Animate the header view to collapsed or expanded if it is dragged only partially
func animateHeaderViewHeight () -> Void {
Logger.verbose("animateHeaderViewHeight")
var headerViewHeightDestinationConstant : CGFloat = 0.0
if (headerViewHeight < ((expandedHeaderViewHeight - collapsedHeaderViewHeight) / 2.0 + collapsedHeaderViewHeight)) {
headerViewHeightDestinationConstant = collapsedHeaderViewHeight
} else {
headerViewHeightDestinationConstant = expandedHeaderViewHeight
}
if (headerViewHeight != expandedHeaderViewHeight && headerViewHeight != collapsedHeaderViewHeight) {
let animationDuration = 0.25
UIView.animate(withDuration: animationDuration, animations: { () -> Void in
self.headerViewHeight = headerViewHeightDestinationConstant
let progress = (self.headerViewHeight - self.collapsedHeaderViewHeight) / (self.expandedHeaderViewHeight - self.collapsedHeaderViewHeight)
self.headerView.expandToProgress(progress)
self.view.layoutIfNeeded()
})
}
}
}
extension APDynamicHeaderTableViewController : UICollectionViewDelegate {
}
extension APDynamicHeaderTableViewController : UIScrollViewDelegate {
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
// Clamp the beginning point to 0 and the max content offset to prevent unintentional resizing when dragging during rubber banding
tableViewScrollOffsetBeginDraggingY = min(max(scrollView.contentOffset.y, 0), scrollView.contentSize.height - scrollView.frame.size.height)
// Keep track of whether or not the header was collapsed to determine if we can add the delay of expansion
headerBeganCollapsed = (headerViewHeight == collapsedHeaderViewHeight)
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
// Do nothing if the table view is not scrollable
if feedCV.contentSize.height < feedCV.bounds.height {
return
}
var contentOffsetY = feedCV.contentOffset.y - tableViewScrollOffsetBeginDraggingY
// Add a delay to expanding the header only if the user began scrolling below the allotted amount of space to actually expand the header with no delay (e.g. If it takes 30 pixels to scroll up the scrollview to expand the header then don't add the delay of the user started scrolling at 10 pixels)
if tableViewScrollOffsetBeginDraggingY > ((expandedHeaderViewHeight - collapsedHeaderViewHeight) + headerExpandDelay) && contentOffsetY < 0 && headerBeganCollapsed {
contentOffsetY = contentOffsetY + headerExpandDelay
}
// Calculate how much the header height will change so we can readjust the table view's content offset so it doesn't scroll while we change the height of the header
let changeInHeaderViewHeight = headerViewHeight - min(max(headerViewHeight - contentOffsetY, collapsedHeaderViewHeight), expandedHeaderViewHeight)
headerViewHeight = min(max(headerViewHeight - contentOffsetY, collapsedHeaderViewHeight), expandedHeaderViewHeight)
let progress = (headerViewHeight - collapsedHeaderViewHeight) / (expandedHeaderViewHeight - collapsedHeaderViewHeight)
// Logger.verbose("headerViewHeight:",headerViewHeight)
headerView.expandToProgress(progress)
headerView.snp.updateConstraints { (make) -> Void in
make.height.equalTo(headerViewHeight)
}
// When the header view height is changing, freeze the content in the table view
if headerViewHeight != collapsedHeaderViewHeight && headerViewHeight != expandedHeaderViewHeight {
feedCV.contentOffset = CGPoint(x: 0, y: feedCV.contentOffset.y - changeInHeaderViewHeight)
}
}
// Animate the header view when the user ends dragging or flicks the scroll view
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
animateHeaderViewHeight()
}
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
animateHeaderViewHeight()
}
}
extension APDynamicHeaderTableViewController : UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 100
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: VideoCollectionViewCell.ID, for: indexPath) as! VideoCollectionViewCell
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return largeWideSize
}
}