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() { open override func handleNewData() {
topViewOutsideOfScrollArea = templateModel?.anchorHeader ?? false
bottomViewOutsideOfScrollArea = templateModel?.anchorFooter ?? false
setup() setup()
registerWithTable() registerWithTable()
super.handleNewData() super.handleNewData()

View File

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

View File

@ -15,9 +15,9 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController {
private var bottomView: UIView? private var bottomView: UIView?
private var headerView: UIView? private var headerView: UIView?
private var footerView: UIView? private var footerView: UIView?
private var safeAreaView: UIView?
var useMargins: Bool = true var useMargins: Bool = true
public var bottomViewOutsideOfScrollArea: Bool = false public var bottomViewOutsideOfScrollArea: Bool = false
public var topViewOutsideOfScrollArea: Bool = false
private var topViewBottomConstraint: NSLayoutConstraint? private var topViewBottomConstraint: NSLayoutConstraint?
private var bottomViewTopConstraint: NSLayoutConstraint? private var bottomViewTopConstraint: NSLayoutConstraint?
@ -76,14 +76,14 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController {
var totalMinimumSpace: CGFloat = 0 var totalMinimumSpace: CGFloat = 0
var fillTop = false var fillTop = false
if spaceBelowTopView() == nil, self.tableView?.tableHeaderView != nil { if spaceBelowTopView() == nil, tableView.tableHeaderView != nil {
fillTop = true fillTop = true
currentSpace += topViewBottomConstraint?.constant ?? 0 currentSpace += topViewBottomConstraint?.constant ?? 0
totalMinimumSpace += minimumSpace totalMinimumSpace += minimumSpace
} }
var fillBottom = false var fillBottom = false
if spaceAboveBottomView() == nil, !bottomViewOutsideOfScrollArea, self.tableView?.tableFooterView != nil { if spaceAboveBottomView() == nil, tableView.tableFooterView != nil {
fillBottom = true fillBottom = true
currentSpace += bottomViewTopConstraint?.constant ?? 0 currentSpace += bottomViewTopConstraint?.constant ?? 0
totalMinimumSpace += minimumSpace totalMinimumSpace += minimumSpace
@ -109,12 +109,7 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController {
showHeader(width) showHeader(width)
showFooter(width) showFooter(width)
} else if fillTop { } 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. topViewBottomConstraint?.constant = newSpace
if bottomViewOutsideOfScrollArea {
topViewBottomConstraint?.constant = newSpace / 2
} else {
topViewBottomConstraint?.constant = newSpace
}
showHeader(width) showHeader(width)
} else if fillBottom { } else if fillBottom {
// Only bottom is spaced. // Only bottom is spaced.
@ -127,9 +122,14 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController {
//MARK: - Header Footer //MARK: - Header Footer
/// Gets the top view and adds it to a spacing view, headerView, and then calls showHeader. /// Gets the top view and adds it to a spacing view, headerView, and then calls showHeader.
open func createViewForTableHeader() { open func createViewForTableHeader() {
let topView = viewForTop() var topView = viewForTop()
self.topView = topView 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() let headerView = MVMCoreUICommonViewsUtility.commonView()
headerView.addSubview(topView) headerView.addSubview(topView)
topView.topAnchor.constraint(equalTo: headerView.topAnchor).isActive = true 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. /// Gets the bottom view and adds it to a spacing view, footerView, and then calls showFooter.
open func createViewForTableFooter() { open func createViewForTableFooter() {
let bottomView = viewForBottom() var bottomView = viewForBottom()
self.bottomView = bottomView 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() let footerView = MVMCoreUICommonViewsUtility.commonView()
footerView.addSubview(bottomView) footerView.addSubview(bottomView)
bottomViewTopConstraint = bottomView.topAnchor.constraint(equalTo: footerView.topAnchor, constant: spaceAboveBottomView() ?? 0) bottomViewTopConstraint = bottomView.topAnchor.constraint(equalTo: footerView.topAnchor, constant: spaceAboveBottomView() ?? 0)
@ -161,10 +166,20 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController {
func showHeader(_ sizingWidth: CGFloat?) { func showHeader(_ sizingWidth: CGFloat?) {
headerView?.removeFromSuperview() headerView?.removeFromSuperview()
tableView?.tableHeaderView = nil tableView?.tableHeaderView = nil
guard let headerView = headerView else { guard let topView = topView,
return 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. // This extra view is needed because of the wonkiness of apple's table header. Things breaks if using autolayout.
headerView.setNeedsLayout() headerView.setNeedsLayout()
headerView.layoutIfNeeded() headerView.layoutIfNeeded()
@ -173,41 +188,42 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController {
tableHeaderView.addSubview(headerView) tableHeaderView.addSubview(headerView)
NSLayoutConstraint.constraintPinSubview(toSuperview: headerView) NSLayoutConstraint.constraintPinSubview(toSuperview: headerView)
tableView?.tableHeaderView = tableHeaderView tableView?.tableHeaderView = tableHeaderView
} }
/// Takes the current footerView and adds it to the tableFooterView /// Takes the current footerView and adds it to the tableFooterView
func showFooter(_ sizingWidth: CGFloat?) { func showFooter(_ sizingWidth: CGFloat?) {
footerView?.removeFromSuperview() footerView?.removeFromSuperview()
safeAreaView?.removeFromSuperview() guard let bottomView = bottomView,
guard let footerView = footerView, let tableView = tableView else { let footerView = footerView,
return let tableView = tableView else {
self.tableView?.tableFooterView = nil
return
} }
if bottomViewOutsideOfScrollArea { if bottomViewOutsideOfScrollArea {
// put bottom view outside of scrolling area. // put bottom view outside of scrolling area.
bottomConstraint?.isActive = false bottomConstraint?.isActive = false
view.addSubview(footerView) view.addSubview(bottomView)
footerView.topAnchor.constraint(equalTo: tableView.bottomAnchor).isActive = true bottomView.topAnchor.constraint(equalTo: tableView.bottomAnchor).isActive = true
footerView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true bottomView.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor).isActive = true
view.rightAnchor.constraint(equalTo: footerView.rightAnchor).isActive = true view.safeAreaLayoutGuide.rightAnchor.constraint(equalTo: bottomView.rightAnchor).isActive = true
view.safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: footerView.bottomAnchor).isActive = true view.safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: bottomView.bottomAnchor).isActive = true
safeAreaView = MVMCoreUICommonViewsUtility.getAndSetupSafeAreaView(on: view)
safeAreaView?.backgroundColor = bottomView?.backgroundColor
} else { } else {
bottomConstraint?.isActive = true 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 //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. // The bottom view can be put outside of the scrolling area.
var bottomViewOutsideOfScroll = false var bottomViewOutsideOfScroll = false
private var safeAreaView: UIView?
var heightConstraint: NSLayoutConstraint? var heightConstraint: NSLayoutConstraint?
open override func updateViews() { open override func updateViews() {
@ -71,7 +70,6 @@ open class ThreeLayerViewController: ProgrammaticScrollViewController {
topView?.removeFromSuperview() topView?.removeFromSuperview()
middleView?.removeFromSuperview() middleView?.removeFromSuperview()
bottomView?.removeFromSuperview() bottomView?.removeFromSuperview()
safeAreaView?.removeFromSuperview()
if let subViews = contentView?.subviews { if let subViews = contentView?.subviews {
for view in subViews { for view in subViews {
view.removeFromSuperview() view.removeFromSuperview()
@ -266,10 +264,6 @@ extension ThreeLayerViewController {
NSLayoutConstraint.pinViewLeft(toSuperview: view, useMargins: useMargins, constant: 0).isActive = true NSLayoutConstraint.pinViewLeft(toSuperview: view, useMargins: useMargins, constant: 0).isActive = true
NSLayoutConstraint.pinViewRight(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 parentView.safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
if let safeAreaView = MVMCoreUICommonViewsUtility.getAndSetupSafeAreaView(on: parentView) {
safeAreaView.backgroundColor = bottomView?.backgroundColor
self.safeAreaView = safeAreaView
}
} }
} }
} }