Created
June 25, 2018 13:05
-
-
Save FabianTerhorst/495493358c6987168c4f79aadec4090e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
open class NestedVerticalCellCollectionViewLayout<V: LayoutAdapterCollectionView, C: Collection>: BaseLayout<V>, ConfigurableLayout where C.Iterator.Element == Layout { | |
private let sectionLayouts: [Section<C>] | |
public init(sectionLayouts: [Section<C>], alignment: Alignment = .topFill, viewReuseId: String? = nil, config: ((V) -> Void)? = nil) { | |
self.sectionLayouts = sectionLayouts | |
super.init(alignment: alignment, flexibility: Flexibility(horizontal: nil, vertical: Flexibility.defaultFlex), viewReuseId: viewReuseId, config: config) | |
} | |
private var cachedSectionLayoutMeasurement: [Section<[LayoutMeasurement]>]? | |
private func measure(within maxSize: CGSize = CGSize.zero) -> [Section<[LayoutMeasurement]>] { | |
if let cachedSectionLayoutMeasurement = cachedSectionLayoutMeasurement { | |
return cachedSectionLayoutMeasurement | |
} | |
let measurement = self.sectionLayouts.map { | |
sectionLayout in | |
return sectionLayout.map { (layout: Layout) -> LayoutMeasurement in | |
return layout.measurement(within: maxSize) | |
} | |
} | |
cachedSectionLayoutMeasurement = measurement | |
return measurement | |
} | |
open func measurement(within maxSize: CGSize) -> LayoutMeasurement { | |
let fullHeight = measure(within: maxSize).reduce(0) { | |
(fullHeight, measuredSection) -> CGFloat in | |
let headerHeight = measuredSection.header?.size.height ?? 0 | |
let footerHeight = measuredSection.footer?.size.height ?? 0 | |
let fullItemsHeight = measuredSection.items.map({ $0.size.height }).reduce(0, +) | |
return fullHeight + headerHeight + footerHeight + fullItemsHeight | |
} | |
// No intrinsic width, but want to be tall enough for all cell heights | |
let size = CGSize(width: 0, height: min(fullHeight, maxSize.height)) | |
return LayoutMeasurement(layout: self, size: size, maxSize: maxSize, sublayouts: []) | |
} | |
private var sectionArrangements: [Section<[LayoutArrangement]>]? = nil | |
open func arrangement(within rect: CGRect, measurement: LayoutMeasurement) -> LayoutArrangement { | |
sectionArrangements = measure().map({ sectionMeasurement in | |
return sectionMeasurement.map({ (measurement: LayoutMeasurement) -> LayoutArrangement in | |
let rect = CGRect(x: 0, y: 0, width: rect.width, height: measurement.size.height) | |
return measurement.arrangement(within: rect) | |
}) | |
}) | |
let frame = Alignment.fill.position(size: measurement.size, in: rect) | |
return LayoutArrangement(layout: self, frame: frame, sublayouts: []) | |
} | |
open override func configure(view: V) { | |
super.configure(view: view) | |
if let sectionArrangements = sectionArrangements { | |
view.layoutAdapter.reload(arrangement: sectionArrangements) | |
} | |
} | |
open override var needsView: Bool { | |
return super.needsView || sectionArrangements != nil | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment