add anchor logic to table three layer and list

Safe area for scrollview
remove safeAreaView itself for now until requirement comes in
This commit is contained in:
Pfeil, Scott Robert 2020-04-22 12:11:33 -04:00
parent a697fea926
commit 9366469f35
4 changed files with 59 additions and 45 deletions

View File

@ -81,6 +81,8 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
}
open override func handleNewData() {
topViewOutsideOfScrollArea = templateModel?.anchorHeader ?? false
bottomViewOutsideOfScrollArea = templateModel?.anchorFooter ?? false
setup()
registerWithTable()
super.handleNewData()

View File

@ -39,11 +39,13 @@ open class ProgrammaticScrollViewController: ScrollingViewController {
topConstraint = constraints?[ConstraintTop] as? NSLayoutConstraint
bottomConstraint = constraints?[ConstraintBot] as? NSLayoutConstraint
// Sets the constraints for the content view
let contentView = MVMCoreUICommonViewsUtility.commonView()
scrollView.addSubview(contentView)
// Sets the constraints for the content view
NSLayoutConstraint.constraintPinSubview(toSuperview: contentView)
contentView.leftAnchor.constraint(equalTo: scrollView.safeAreaLayoutGuide.leftAnchor).isActive = true
scrollView.safeAreaLayoutGuide.rightAnchor.constraint(equalTo: contentView.rightAnchor).isActive = true
contentView.topAnchor.constraint(equalTo: scrollView.safeAreaLayoutGuide.topAnchor).isActive = true
scrollView.safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
// Super will set later.
contentWidthConstraint = contentView.widthAnchor.constraint(equalToConstant: 320.0)

View File

@ -15,9 +15,9 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController {
private var bottomView: UIView?
private var headerView: UIView?
private var footerView: UIView?
private var safeAreaView: UIView?
var useMargins: Bool = true
public var bottomViewOutsideOfScrollArea: Bool = false
public var topViewOutsideOfScrollArea: Bool = false
private var topViewBottomConstraint: NSLayoutConstraint?
private var bottomViewTopConstraint: NSLayoutConstraint?
@ -76,14 +76,14 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController {
var totalMinimumSpace: CGFloat = 0
var fillTop = false
if spaceBelowTopView() == nil, self.tableView?.tableHeaderView != nil {
if spaceBelowTopView() == nil, tableView.tableHeaderView != nil {
fillTop = true
currentSpace += topViewBottomConstraint?.constant ?? 0
totalMinimumSpace += minimumSpace
}
var fillBottom = false
if spaceAboveBottomView() == nil, !bottomViewOutsideOfScrollArea, self.tableView?.tableFooterView != nil {
if spaceAboveBottomView() == nil, tableView.tableFooterView != nil {
fillBottom = true
currentSpace += bottomViewTopConstraint?.constant ?? 0
totalMinimumSpace += minimumSpace
@ -109,12 +109,7 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController {
showHeader(width)
showFooter(width)
} else if fillTop {
// Only top is spaced (half the size if the bottom view is out of the scroll because it needs to be sized as if there are two spacers but there is only one.
if bottomViewOutsideOfScrollArea {
topViewBottomConstraint?.constant = newSpace / 2
} else {
topViewBottomConstraint?.constant = newSpace
}
topViewBottomConstraint?.constant = newSpace
showHeader(width)
} else if fillBottom {
// Only bottom is spaced.
@ -127,9 +122,14 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController {
//MARK: - Header Footer
/// Gets the top view and adds it to a spacing view, headerView, and then calls showHeader.
open func createViewForTableHeader() {
let topView = viewForTop()
var topView = viewForTop()
self.topView = topView
// If top view is outside of scroll area, create a dummy view for the header.
if topViewOutsideOfScrollArea {
topView = MVMCoreUICommonViewsUtility.commonView()
topView.heightAnchor.constraint(equalToConstant: 0.5).isActive = true
}
let headerView = MVMCoreUICommonViewsUtility.commonView()
headerView.addSubview(topView)
topView.topAnchor.constraint(equalTo: headerView.topAnchor).isActive = true
@ -143,9 +143,14 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController {
/// Gets the bottom view and adds it to a spacing view, footerView, and then calls showFooter.
open func createViewForTableFooter() {
let bottomView = viewForBottom()
var bottomView = viewForBottom()
self.bottomView = bottomView
// If bottom view is outside of scroll area, create a dummy view for the header.
if bottomViewOutsideOfScrollArea {
bottomView = MVMCoreUICommonViewsUtility.commonView()
bottomView.heightAnchor.constraint(equalToConstant: 0.5).isActive = true
}
let footerView = MVMCoreUICommonViewsUtility.commonView()
footerView.addSubview(bottomView)
bottomViewTopConstraint = bottomView.topAnchor.constraint(equalTo: footerView.topAnchor, constant: spaceAboveBottomView() ?? 0)
@ -161,10 +166,20 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController {
func showHeader(_ sizingWidth: CGFloat?) {
headerView?.removeFromSuperview()
tableView?.tableHeaderView = nil
guard let headerView = headerView else {
return
}
guard let topView = topView,
let headerView = headerView else { return }
if topViewOutsideOfScrollArea {
// put top view outside of scrolling area.
topConstraint?.isActive = false
view.addSubview(topView)
topView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
topView.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor).isActive = true
view.safeAreaLayoutGuide.rightAnchor.constraint(equalTo: topView.rightAnchor).isActive = true
tableView.topAnchor.constraint(equalTo: topView.bottomAnchor).isActive = true
} else {
topConstraint?.isActive = true
}
// This extra view is needed because of the wonkiness of apple's table header. Things breaks if using autolayout.
headerView.setNeedsLayout()
headerView.layoutIfNeeded()
@ -173,41 +188,42 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController {
tableHeaderView.addSubview(headerView)
NSLayoutConstraint.constraintPinSubview(toSuperview: headerView)
tableView?.tableHeaderView = tableHeaderView
}
/// Takes the current footerView and adds it to the tableFooterView
func showFooter(_ sizingWidth: CGFloat?) {
footerView?.removeFromSuperview()
safeAreaView?.removeFromSuperview()
guard let footerView = footerView, let tableView = tableView else {
return
guard let bottomView = bottomView,
let footerView = footerView,
let tableView = tableView else {
self.tableView?.tableFooterView = nil
return
}
if bottomViewOutsideOfScrollArea {
// put bottom view outside of scrolling area.
bottomConstraint?.isActive = false
view.addSubview(footerView)
footerView.topAnchor.constraint(equalTo: tableView.bottomAnchor).isActive = true
footerView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
view.rightAnchor.constraint(equalTo: footerView.rightAnchor).isActive = true
view.safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: footerView.bottomAnchor).isActive = true
safeAreaView = MVMCoreUICommonViewsUtility.getAndSetupSafeAreaView(on: view)
safeAreaView?.backgroundColor = bottomView?.backgroundColor
view.addSubview(bottomView)
bottomView.topAnchor.constraint(equalTo: tableView.bottomAnchor).isActive = true
bottomView.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor).isActive = true
view.safeAreaLayoutGuide.rightAnchor.constraint(equalTo: bottomView.rightAnchor).isActive = true
view.safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: bottomView.bottomAnchor).isActive = true
} else {
bottomConstraint?.isActive = true
var y: CGFloat?
if let tableFooterView = tableView.tableFooterView {
// if footer already exists, use the same y location to avoid strange moving animation
y = tableFooterView.frame.minY
}
// This extra view is needed because of the wonkiness of apple's table footer. Things breaks if using autolayout.
MVMCoreUIUtility.sizeView(toFit: footerView)
let tableFooterView = UIView(frame: CGRect(x: 0, y: y ?? 0, width: MVMCoreUIUtility.getWidth(), height: footerView.frame.height))
tableFooterView.addSubview(footerView)
NSLayoutConstraint.constraintPinSubview(toSuperview: footerView)
tableView.tableFooterView = tableFooterView
}
var y: CGFloat?
if let tableFooterView = tableView.tableFooterView {
// if footer already exists, use the same y location to avoid strange moving animation
y = tableFooterView.frame.minY
}
// This extra view is needed because of the wonkiness of apple's table footer. Things breaks if using autolayout.
MVMCoreUIUtility.sizeView(toFit: footerView)
let tableFooterView = UIView(frame: CGRect(x: 0, y: y ?? 0, width: MVMCoreUIUtility.getWidth(), height: footerView.frame.height))
tableFooterView.addSubview(footerView)
NSLayoutConstraint.constraintPinSubview(toSuperview: footerView)
tableView.tableFooterView = tableFooterView
}
//MARK: - Functions to subclass

View File

@ -24,7 +24,6 @@ open class ThreeLayerViewController: ProgrammaticScrollViewController {
// The bottom view can be put outside of the scrolling area.
var bottomViewOutsideOfScroll = false
private var safeAreaView: UIView?
var heightConstraint: NSLayoutConstraint?
open override func updateViews() {
@ -71,7 +70,6 @@ open class ThreeLayerViewController: ProgrammaticScrollViewController {
topView?.removeFromSuperview()
middleView?.removeFromSuperview()
bottomView?.removeFromSuperview()
safeAreaView?.removeFromSuperview()
if let subViews = contentView?.subviews {
for view in subViews {
view.removeFromSuperview()
@ -266,10 +264,6 @@ extension ThreeLayerViewController {
NSLayoutConstraint.pinViewLeft(toSuperview: view, useMargins: useMargins, constant: 0).isActive = true
NSLayoutConstraint.pinViewRight(toSuperview: view, useMargins: useMargins, constant: 0).isActive = true
parentView.safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
if let safeAreaView = MVMCoreUICommonViewsUtility.getAndSetupSafeAreaView(on: parentView) {
safeAreaView.backgroundColor = bottomView?.backgroundColor
self.safeAreaView = safeAreaView
}
}
}
}