Open abkama0a opened 6 years ago
I have the same problem, how to solve it?
Here's my current workaround which I think is not a perfect solution:
add the following extension and custom class to your project:
class CVHeader {
var value: CGFloat = 30.0
}
private var headerKey: UInt8 = 0
extension AlignedCollectionViewFlowLayout {
var headerHeight: CVHeader {
get {
return associatedObject(base: self, key: &headerKey)
{ return CVHeader() }
}
set { associateObject(base: self, key: &headerKey, value: newValue) }
}
func associatedObject<ValueType: AnyObject>(
base: AnyObject,
key: UnsafePointer<UInt8>,
initialiser: () -> ValueType)
-> ValueType {
if let associated = objc_getAssociatedObject(base, key)
as? ValueType { return associated }
let associated = initialiser()
objc_setAssociatedObject(base, key, associated,
.OBJC_ASSOCIATION_RETAIN)
return associated
}
func associateObject<ValueType: AnyObject>(
base: AnyObject,
key: UnsafePointer<UInt8>,
value: ValueType) {
objc_setAssociatedObject(base, key, value,
.OBJC_ASSOCIATION_RETAIN)
}
override open func layoutAttributesForSupplementaryView(ofKind elementKind: String, at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
guard let attributes = super.layoutAttributesForSupplementaryView(ofKind: elementKind, at: indexPath)?.copy() as? UICollectionViewLayoutAttributes else {
return nil
}
let yPos:CGFloat = layoutAttributesForItem(at: indexPath)!.frame.origin.y - headerHeight.value
attributes.frame = CGRect(x: 0.0, y: yPos, width: (collectionView?.frame.width)!, height: headerHeight.value)
return attributes
}
}
Then, in your viewController where you are implementing the AlignedCollectionViewFlowLayout, override the viewDidAppear function as follows:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
UIView.performWithoutAnimation {
yourCollectionView.reloadItems(at: [IndexPath(row: yourArray.count - 1, section: yourLastSectionIndex)])
}
}
You'll also need to edit the AlignedCollectionViewFlowLayout.swift file. You need to edit the private setFrame function as follows:
private func setFrame(forLayoutAttributes layoutAttributes: UICollectionViewLayoutAttributes) {
if layoutAttributes.representedElementCategory == .cell { // Do not modify header views etc.
let indexPath = layoutAttributes.indexPath
if let newFrame = layoutAttributesForItem(at: indexPath)?.frame {
layoutAttributes.frame = newFrame
}
} else if layoutAttributes.representedElementCategory == .supplementaryView {
if layoutAttributes.representedElementKind == UICollectionElementKindSectionHeader {
if let newFrame = layoutAttributesForSupplementaryView(ofKind: UICollectionElementKindSectionHeader, at: layoutAttributes.indexPath)?.frame {
layoutAttributes.frame = newFrame
}
}
}
}
if setFrame wasn't private, we could've overridden it in the extension and never had to worry about updating this in the future if the original author update this library. I hope this help you.
I am having a hard time trying to add header sections along with your awesome AlignedcollectionViewFlowLayout, but my attempts are failing.
What I did so far was adding layoutAttributesForSupplementaryView:ofKind:at to your .swift file and modifying your setFrame function to process UICollectionElementKindSectionHeader. I also added a public var for header's height: headerHeight
and
My implementation seems to work right, but when I segue to my ViewController where I am implementing your custom flow layout, viewForSupplementaryElementOfKind is called too soon before the correct attributes are calculated. I know this because I am triggering a call to viewForSupplementaryElementOfKind by reloadItems(at:) inside collectionView:didSelectItemAt
(Edit: I added the following block to my viewDidAppear to work around this delay
)
I've also printed frame values for first cell in section as well as the header frame. It seems that my attributes are calculated 4 times and the viewForSupplementaryElementOfKind function takes values from the 3rd call
Edit: see attachment for screens after segueing to VC, log from console about first cell in section and header saved frame, and screen of collectionView after triggering didSelectItemAt or reloadingItems in viewDidAppear
I'd really appreciate it if you'd help me to avoid making extra call to reloadItems(at:)