240 lines
9.5 KiB
Swift
240 lines
9.5 KiB
Swift
//
|
|
// Container.swift
|
|
// MVMCoreUI
|
|
//
|
|
// Created by Scott Pfeil on 12/11/19.
|
|
// Copyright © 2019 Verizon Wireless. All rights reserved.
|
|
//
|
|
|
|
import UIKit
|
|
|
|
public protocol ContainerModelProtocol {
|
|
var horizontalAlignment: UIStackView.Alignment? { get set }
|
|
var verticalAlignment: UIStackView.Alignment? { get set }
|
|
var useHorizontalMargins: Bool? { get set }
|
|
var useVerticalMargins: Bool? { get set }
|
|
}
|
|
|
|
public class ContainerHelper: NSObject {
|
|
var leftConstraint: NSLayoutConstraint?
|
|
var topConstraint: NSLayoutConstraint?
|
|
var bottomConstraint: NSLayoutConstraint?
|
|
var rightConstraint: NSLayoutConstraint?
|
|
|
|
var alignCenterHorizontalConstraint: NSLayoutConstraint?
|
|
var alignCenterLeftConstraint: NSLayoutConstraint?
|
|
var alignCenterRightConstraint: NSLayoutConstraint?
|
|
|
|
var alignCenterVerticalConstraint: NSLayoutConstraint?
|
|
var alignCenterTopConstraint: NSLayoutConstraint?
|
|
var alignCenterBottomConstraint: NSLayoutConstraint?
|
|
|
|
var leftLowConstraint: NSLayoutConstraint?
|
|
var topLowConstraint: NSLayoutConstraint?
|
|
var bottomLowConstraint: NSLayoutConstraint?
|
|
var rightLowConstraint: NSLayoutConstraint?
|
|
|
|
func constrainView(_ view: UIView) {
|
|
guard let margins = view.superview?.layoutMarginsGuide else { return }
|
|
leftConstraint = view.leftAnchor.constraint(equalTo: margins.leftAnchor)
|
|
leftConstraint?.isActive = true
|
|
|
|
topConstraint = view.topAnchor.constraint(equalTo: margins.topAnchor)
|
|
topConstraint?.isActive = true
|
|
|
|
rightConstraint = margins.rightAnchor.constraint(equalTo: view.rightAnchor)
|
|
rightConstraint?.isActive = true
|
|
|
|
bottomConstraint = margins.bottomAnchor.constraint(equalTo: view.bottomAnchor)
|
|
bottomConstraint?.isActive = true
|
|
|
|
alignCenterHorizontalConstraint = view.centerXAnchor.constraint(equalTo: margins.centerXAnchor)
|
|
alignCenterLeftConstraint = view.leftAnchor.constraint(greaterThanOrEqualTo: margins.leftAnchor)
|
|
alignCenterRightConstraint = margins.rightAnchor.constraint(greaterThanOrEqualTo: view.rightAnchor)
|
|
|
|
alignCenterVerticalConstraint = view.centerYAnchor.constraint(equalTo: margins.centerYAnchor)
|
|
alignCenterTopConstraint = view.topAnchor.constraint(greaterThanOrEqualTo: margins.topAnchor)
|
|
alignCenterBottomConstraint = margins.bottomAnchor.constraint(greaterThanOrEqualTo: view.bottomAnchor)
|
|
|
|
leftLowConstraint = view.leftAnchor.constraint(equalTo: margins.leftAnchor)
|
|
leftLowConstraint?.priority = UILayoutPriority(rawValue: 200)
|
|
leftLowConstraint?.isActive = true
|
|
|
|
topLowConstraint = view.topAnchor.constraint(equalTo: margins.topAnchor)
|
|
topLowConstraint?.priority = UILayoutPriority(rawValue: 200)
|
|
topLowConstraint?.isActive = true
|
|
|
|
rightLowConstraint = margins.rightAnchor.constraint(equalTo: view.rightAnchor)
|
|
rightLowConstraint?.priority = UILayoutPriority(rawValue: 200)
|
|
rightLowConstraint?.isActive = true
|
|
|
|
bottomLowConstraint = margins.bottomAnchor.constraint(equalTo: view.bottomAnchor)
|
|
bottomLowConstraint?.priority = UILayoutPriority(rawValue: 200)
|
|
bottomLowConstraint?.isActive = true
|
|
|
|
setAccessibility(view)
|
|
}
|
|
|
|
func setAccessibility(_ view: UIView) {
|
|
guard let superView = view.superview else { return }
|
|
superView.isAccessibilityElement = false
|
|
if let elements = view.accessibilityElements {
|
|
superView.accessibilityElements = elements
|
|
} else {
|
|
superView.accessibilityElements = [view]
|
|
}
|
|
}
|
|
|
|
func alignHorizontal(_ alignment: UIStackView.Alignment) {
|
|
switch alignment {
|
|
case .center:
|
|
alignCenterHorizontalConstraint?.isActive = true
|
|
alignCenterLeftConstraint?.isActive = true
|
|
alignCenterRightConstraint?.isActive = true
|
|
leftConstraint?.isActive = false
|
|
rightConstraint?.isActive = false
|
|
case .leading:
|
|
alignCenterHorizontalConstraint?.isActive = false
|
|
alignCenterLeftConstraint?.isActive = false
|
|
alignCenterRightConstraint?.isActive = true
|
|
leftConstraint?.isActive = true
|
|
rightConstraint?.isActive = false
|
|
case .trailing:
|
|
alignCenterHorizontalConstraint?.isActive = false
|
|
alignCenterLeftConstraint?.isActive = true
|
|
alignCenterRightConstraint?.isActive = false
|
|
leftConstraint?.isActive = false
|
|
rightConstraint?.isActive = true
|
|
case .fill:
|
|
alignCenterHorizontalConstraint?.isActive = false
|
|
alignCenterLeftConstraint?.isActive = false
|
|
alignCenterRightConstraint?.isActive = false
|
|
leftConstraint?.isActive = true
|
|
rightConstraint?.isActive = true
|
|
default: break
|
|
}
|
|
}
|
|
|
|
func alignVertical(_ alignment: UIStackView.Alignment) {
|
|
switch alignment {
|
|
case .center:
|
|
alignCenterVerticalConstraint?.isActive = true
|
|
alignCenterTopConstraint?.isActive = true
|
|
alignCenterBottomConstraint?.isActive = true
|
|
topConstraint?.isActive = false
|
|
bottomConstraint?.isActive = false
|
|
case .leading:
|
|
alignCenterVerticalConstraint?.isActive = false
|
|
alignCenterTopConstraint?.isActive = false
|
|
alignCenterBottomConstraint?.isActive = true
|
|
topConstraint?.isActive = true
|
|
bottomConstraint?.isActive = false
|
|
case .trailing:
|
|
alignCenterVerticalConstraint?.isActive = false
|
|
alignCenterTopConstraint?.isActive = true
|
|
alignCenterBottomConstraint?.isActive = false
|
|
topConstraint?.isActive = false
|
|
bottomConstraint?.isActive = true
|
|
case .fill:
|
|
alignCenterVerticalConstraint?.isActive = false
|
|
alignCenterTopConstraint?.isActive = false
|
|
alignCenterBottomConstraint?.isActive = false
|
|
topConstraint?.isActive = true
|
|
bottomConstraint?.isActive = true
|
|
default: break
|
|
}
|
|
}
|
|
|
|
func set(with model: ContainerModelProtocol) {
|
|
if let horizontalAlignment = model.horizontalAlignment {
|
|
alignHorizontal(horizontalAlignment)
|
|
}
|
|
if let verticalAlignment = model.verticalAlignment {
|
|
alignVertical(verticalAlignment)
|
|
}
|
|
}
|
|
|
|
static func getAlignment(for string: String) -> UIStackView.Alignment? {
|
|
switch string {
|
|
case "leading":
|
|
return .leading
|
|
case "trailing":
|
|
return .trailing
|
|
case "center":
|
|
return .center
|
|
case "fill":
|
|
return .fill
|
|
default:
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func set(with JSON: [AnyHashable: Any]?, for contained: UIView) {
|
|
if let horizontalAlignmentString = JSON?.optionalStringForKey("horizontalAlignment"), let alignment = ContainerHelper.getAlignment(for: horizontalAlignmentString) ?? (contained as? MVMCoreUIViewConstrainingProtocol)?.horizontalAlignment?() {
|
|
alignHorizontal(alignment)
|
|
} else if let alignment = (contained as? MVMCoreUIViewConstrainingProtocol)?.horizontalAlignment?() {
|
|
alignHorizontal(alignment)
|
|
}
|
|
|
|
if let verticalAlignmentString = JSON?.optionalStringForKey("verticalAlignment"), let alignment = ContainerHelper.getAlignment(for: verticalAlignmentString) ?? (contained as? MVMCoreUIViewConstrainingProtocol)?.verticalAlignment?() {
|
|
alignVertical(alignment)
|
|
} else if let alignment = (contained as? MVMCoreUIViewConstrainingProtocol)?.verticalAlignment?() {
|
|
alignVertical(alignment)
|
|
}
|
|
}
|
|
}
|
|
|
|
open class Container: View {
|
|
var containerModel: ContainerModelProtocol?
|
|
var view: UIView?
|
|
let containerHelper = ContainerHelper()
|
|
|
|
var topMarginPadding: CGFloat = 0
|
|
var bottomMarginPadding: CGFloat = 0
|
|
}
|
|
|
|
// MARK: - MVMCoreViewProtocol
|
|
public extension Container {
|
|
override func updateView(_ size: CGFloat) {
|
|
super.updateView(size)
|
|
(view as? MVMCoreViewProtocol)?.updateView(size)
|
|
MFStyler.setMarginsFor(self, size: size, defaultHorizontal: containerModel?.useHorizontalMargins ?? true, top: containerModel?.useHorizontalMargins ?? true ? topMarginPadding : 0, bottom: containerModel?.useHorizontalMargins ?? true ? bottomMarginPadding : 0)
|
|
}
|
|
|
|
/// Will be called only once.
|
|
override func setupView() {
|
|
super.setupView()
|
|
backgroundColor = .clear
|
|
}
|
|
|
|
func addAndContain(_ view: UIView) {
|
|
view.translatesAutoresizingMaskIntoConstraints = false
|
|
addSubview(view)
|
|
containerHelper.constrainView(view)
|
|
self.view = view
|
|
}
|
|
|
|
convenience init(andContain view: UIView) {
|
|
self.init()
|
|
addAndContain(view)
|
|
}
|
|
}
|
|
|
|
// MARK: - MVMCoreUIMoleculeViewProtocol
|
|
public extension Container {
|
|
override func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) {
|
|
super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
|
|
guard let view = view else { return }
|
|
containerHelper.set(with: json, for: view)
|
|
}
|
|
|
|
override func reset() {
|
|
super.reset()
|
|
(view as? MVMCoreUIMoleculeViewProtocol)?.reset?()
|
|
}
|
|
|
|
override func setAsMolecule() {
|
|
(view as? MVMCoreUIMoleculeViewProtocol)?.setAsMolecule?()
|
|
}
|
|
}
|