This commit is contained in:
Pfeil, Scott Robert 2020-04-22 14:03:02 -04:00
parent 9366469f35
commit 02e1de9b88
3 changed files with 25 additions and 62 deletions

View File

@ -17,6 +17,8 @@ import Foundation
private var footerView: ContainerCollectionReusableView?
private let headerID = "header"
private let footerID = "footer"
public var bottomViewOutsideOfScrollArea: Bool = false
public var topViewOutsideOfScrollArea: Bool = false
/// Updates the padding for flexible space (header or footer)
private func updateFlexibleSpace() {
@ -41,16 +43,8 @@ import Foundation
}
guard fillTop || fillBottom else { return }
let newSpace = MVMCoreUIUtility.getVariableConstraintHeight(currentSpace, in: tableView, minimumHeight: totalMinimumSpace)
// If the bottom view is outside of the scroll, then only the top view constraint is being used, so we have to double it to account for the bottom constraint not being there when we compare to the new value.
var currentSpaceForCompare: CGFloat = currentSpace
if fillTop {
currentSpaceForCompare = currentSpace * 2;
}
if !MVMCoreGetterUtility.cgfequalwiththreshold(newSpace, currentSpaceForCompare, 1) {
if !MVMCoreGetterUtility.cgfequalwiththreshold(newSpace, currentSpace, 1) {
if fillTop && fillBottom {
// space both
let half = newSpace / 2
@ -89,11 +83,11 @@ import Foundation
self.invalidateCollectionLayout()
}
}
open override func handleNewData() {
super.handleNewData()
createViewForHeader()
createViewForFooter()
topView = viewForTop()
bottomView = viewForBottom()
reloadCollectionData()
}
@ -118,27 +112,6 @@ import Foundation
open func minimumFillSpace() -> CGFloat {
return 0
}
//MARK: - Header Footer
/// Creates the top view.
open func createViewForHeader() {
guard let topView = viewForTop() else {
self.topView = nil
self.headerView = nil
return
}
self.topView = topView
}
/// Creates the footer
open func createViewForFooter() {
guard let bottomView = viewForBottom() else {
self.bottomView = nil
self.footerView = nil
return
}
self.bottomView = bottomView
}
//MARK: - Functions to subclass
/// Subclass for a top view.
@ -187,18 +160,14 @@ import Foundation
}
open func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
guard let _ = topView,
section == 0 else { return .zero }
guard section == 0 else { return .zero }
// Calculate the height of the header since apple doesn't support autolayout. Width is fixed, height is tall as content.
let header = headerView ?? self.collectionView(collectionView, viewForSupplementaryElementOfKind: UICollectionView.elementKindSectionHeader, at: IndexPath(row: 0, section: section))
return header.systemLayoutSizeFitting(CGSize(width: collectionView.frame.width, height: UIView.layoutFittingExpandedSize.height), withHorizontalFittingPriority: .required, verticalFittingPriority: .fittingSizeLevel)
}
open func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize {
guard let _ = bottomView,
section == numberOfSections(in: collectionView) - 1 else { return .zero }
guard section == numberOfSections(in: collectionView) - 1 else { return .zero }
// Calculate the height of the footr since apple doesn't support autolayout. Width is fixed, height is tall as content.
let footer = footerView ?? self.collectionView(collectionView, viewForSupplementaryElementOfKind: UICollectionView.elementKindSectionFooter, at: IndexPath(row: 0, section: section))
return footer.systemLayoutSizeFitting(CGSize(width: collectionView.frame.width, height: UIView.layoutFittingExpandedSize.height), withHorizontalFittingPriority: .required, verticalFittingPriority: .fittingSizeLevel)
@ -207,13 +176,15 @@ import Foundation
open func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
if kind == UICollectionView.elementKindSectionFooter,
let footerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: footerID, for: indexPath) as? ContainerCollectionReusableView {
footerView.addAndContain(view: bottomView!)
let bottomView = self.bottomView ?? MVMCoreUICommonViewsUtility.getView(with: 0)
footerView.addAndContain(view: bottomView)
footerView.topConstraint?.constant = spaceAboveBottomView() ?? 0
self.footerView = footerView
return footerView
} else if kind == UICollectionView.elementKindSectionHeader,
let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: headerID, for: indexPath) as? ContainerCollectionReusableView {
headerView.addAndContain(view: topView!)
let topView = self.topView ?? MVMCoreUICommonViewsUtility.getView(with: 0)
headerView.addAndContain(view: topView)
headerView.bottomConstraint?.constant = spaceBelowTopView() ?? 0
self.headerView = headerView
return headerView

View File

@ -92,15 +92,8 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController {
guard fillTop || fillBottom else { return }
let newSpace = MVMCoreUIUtility.getVariableConstraintHeight(currentSpace, in: tableView, minimumHeight: totalMinimumSpace)
// If the bottom view is outside of the scroll, then only the top view constraint is being used, so we have to double it to account for the bottom constraint not being there when we compare to the new value.
var currentSpaceForCompare: CGFloat = currentSpace
if fillTop && bottomViewOutsideOfScrollArea {
currentSpaceForCompare = currentSpace * 2;
}
let width = view.bounds.width
if !MVMCoreGetterUtility.cgfequalwiththreshold(newSpace, currentSpaceForCompare, 0.1) {
if !MVMCoreGetterUtility.cgfequalwiththreshold(newSpace, currentSpace, 0.1) {
if fillTop && fillBottom {
// space both
let half = newSpace / 2
@ -125,10 +118,9 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController {
var topView = viewForTop()
self.topView = topView
// If top view is outside of scroll area, create a dummy view for the header.
// If top view is outside of scroll area, create a dummy view for the header. Small height is needed to stop apple from adding padding for grouped tables when no header.
if topViewOutsideOfScrollArea {
topView = MVMCoreUICommonViewsUtility.commonView()
topView.heightAnchor.constraint(equalToConstant: 0.5).isActive = true
topView = MVMCoreUICommonViewsUtility.getView(with: 0.5)
}
let headerView = MVMCoreUICommonViewsUtility.commonView()
headerView.addSubview(topView)
@ -146,10 +138,9 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController {
var bottomView = viewForBottom()
self.bottomView = bottomView
// If bottom view is outside of scroll area, create a dummy view for the header.
// If bottom view is outside of scroll area, create a dummy view for the header. Small height is needed to stop apple from adding padding for grouped tables when no header.
if bottomViewOutsideOfScrollArea {
bottomView = MVMCoreUICommonViewsUtility.commonView()
bottomView.heightAnchor.constraint(equalToConstant: 0.5).isActive = true
bottomView = MVMCoreUICommonViewsUtility.getView(with: 0.5)
}
let footerView = MVMCoreUICommonViewsUtility.commonView()
footerView.addSubview(bottomView)
@ -188,7 +179,6 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController {
tableHeaderView.addSubview(headerView)
NSLayoutConstraint.constraintPinSubview(toSuperview: headerView)
tableView?.tableHeaderView = tableHeaderView
}
/// Takes the current footerView and adds it to the tableFooterView
@ -229,18 +219,14 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController {
//MARK: - Functions to subclass
/// Subclass for a top view.
open func viewForTop() -> UIView {
let view = MVMCoreUICommonViewsUtility.commonView()
// Small height is needed to stop apple from adding padding for grouped tables when no header.
view.heightAnchor.constraint(equalToConstant: 1).isActive = true
return view
return MVMCoreUICommonViewsUtility.getView(with: 1)
}
/// Subclass for a bottom view.
open func viewForBottom() -> UIView {
// Default spacing is standard when no buttons.
let view = MVMCoreUICommonViewsUtility.commonView()
view.heightAnchor.constraint(equalToConstant: PaddingDefaultVerticalSpacing).isActive = true
return view
return MVMCoreUICommonViewsUtility.getView(with: PaddingDefaultVerticalSpacing)
}
deinit {

View File

@ -20,4 +20,10 @@ public extension MVMCoreUICommonViewsUtility {
return toolbar
}
static func getView(with height: CGFloat) -> UIView {
let view = self.commonView()
view.heightAnchor.constraint(equalToConstant: height).isActive = true
return view
}
}