vds_ios_sample/VDSSample/ViewControllers/ModelScrollViewController.swift
Matt Bruce b24f90dab7 refactored picker base
Signed-off-by: Matt Bruce <matt.bruce@verizon.com>
2022-10-10 16:35:16 -05:00

211 lines
8.0 KiB
Swift

//
// ModelViewController.swift
// VDSSample
//
// Created by Matt Bruce on 8/15/22.
//
import Foundation
import UIKit
import Combine
import VDS
public class ModelScrollViewController<ModelType: Modelable>: UIViewController, ModelHandlerable, Initable {
deinit {
print("\(Self.self) deinit")
}
private let edgeSpacing = 16.0
private let topBottomSpacing = 20.0
//--------------------------------------------------
// MARK: - Combine Properties
//--------------------------------------------------
@Published public var model: ModelType = ModelType()
public var modelPublisher: Published<ModelType>.Publisher { $model }
public var subscribers = Set<AnyCancellable>()
public var firstRender: Bool = false
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
private var initialSetupPerformed = false
@Proxy(\.model.surface)
open var surface: Surface
@Proxy(\.model.disabled)
open var disabled: Bool
//--------------------------------------------------
// MARK: - Initializers
//--------------------------------------------------
required public init() {
super.init(nibName: nil, bundle: nil)
initialSetup()
set(with: model)
}
public required init(with model: ModelType) {
super.init(nibName: nil, bundle: nil)
initialSetup()
set(with: model)
}
public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nil, bundle: nil)
initialSetup()
}
public required init?(coder: NSCoder) {
super.init(coder: coder)
initialSetup()
}
//--------------------------------------------------
// MARK: - Setup
//--------------------------------------------------
public func initialSetup() {
if !initialSetupPerformed {
initialSetupPerformed = true
setupUpdateView()
setup()
surfacePickerSelectorView.scrollToBottom = { [weak self] in self?.scrollToBottom()}
}
}
public lazy var surfacePickerSelectorView = {
SurfacePickerSelectorView(picker: self.picker)
}()
public var picker: UIPickerView = {
return UIPickerView().with {
$0.backgroundColor = .white
$0.translatesAutoresizingMaskIntoConstraints = false
}
}()
public var contentView: UIView = {
return UIView().with {
$0.translatesAutoresizingMaskIntoConstraints = false
}
}()
public var formStackView: UIStackView = {
return UIStackView().with {
$0.translatesAutoresizingMaskIntoConstraints = false
$0.alignment = .fill
$0.distribution = .fillProportionally
$0.axis = .vertical
$0.spacing = 10
}
}()
public var contentTopView: UIView = {
return UIView().with {
$0.translatesAutoresizingMaskIntoConstraints = false
}
}()
public var contentBottomView: UIView = {
return UIView().with {
$0.translatesAutoresizingMaskIntoConstraints = false
}
}()
open override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
embed(scrollViewController)
scrollViewController.scrollView.alwaysBounceVertical = true
scrollViewController.contentView = contentView
contentView.addSubview(contentTopView)
contentView.addSubview(contentBottomView)
contentBottomView.addSubview(formStackView)
// contentTopView.backgroundColor = .green
// contentBottomView.backgroundColor = .yellow
contentTopView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: edgeSpacing).isActive = true
contentTopView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: edgeSpacing).isActive = true
contentTopView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -edgeSpacing).isActive = true
contentBottomView.topAnchor.constraint(equalTo: contentTopView.bottomAnchor, constant: edgeSpacing).isActive = true
contentBottomView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: edgeSpacing).isActive = true
contentBottomView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -edgeSpacing).isActive = true
contentBottomView.bottomAnchor.constraint(lessThanOrEqualTo: contentView.bottomAnchor, constant: -edgeSpacing).isActive = true
formStackView.topAnchor.constraint(equalTo: contentBottomView.topAnchor, constant: edgeSpacing).isActive = true
formStackView.leadingAnchor.constraint(equalTo: contentBottomView.leadingAnchor, constant: edgeSpacing).isActive = true
formStackView.trailingAnchor.constraint(equalTo: contentBottomView.trailingAnchor, constant: -edgeSpacing).isActive = true
formStackView.bottomAnchor.constraint(equalTo: contentBottomView.bottomAnchor, constant: -100).isActive = true
view.addSubview(picker)
picker.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor).isActive = true
picker.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor).isActive = true
picker.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
picker.isHidden = true
}
private let scrollViewController = ScrollViewController()
public func scrollToBottom() {
let bottomOffset = CGPoint(x: 0, y: scrollViewController.scrollView.contentSize.height - scrollViewController.scrollView.bounds.height + scrollViewController.scrollView.contentInset.bottom)
scrollViewController.scrollView.setContentOffset(bottomOffset, animated: true)
}
private func embed(_ viewController: UIViewController) {
addChild(viewController)
view.addSubview(viewController.view)
viewController.view.translatesAutoresizingMaskIntoConstraints = false
viewController.view.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
viewController.view.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
viewController.view.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
viewController.view.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
viewController.didMove(toParent: self)
}
open func addContentTopView(view: UIView) {
contentTopView.addSubview(view)
view.leadingAnchor.constraint(equalTo: contentTopView.leadingAnchor, constant: edgeSpacing).isActive = true
view.topAnchor.constraint(equalTo: contentTopView.topAnchor, constant: topBottomSpacing).isActive = true
view.trailingAnchor.constraint(lessThanOrEqualTo: contentTopView.trailingAnchor, constant: -edgeSpacing).isActive = true
view.bottomAnchor.constraint(lessThanOrEqualTo: contentTopView.bottomAnchor, constant: -topBottomSpacing).isActive = true
}
open func addFormRow(label: String, view: UIView, stackView: UIStackView? = nil) {
let formRow = UIStackView().with {
$0.translatesAutoresizingMaskIntoConstraints = false
$0.alignment = .fill
$0.distribution = .fillEqually
$0.axis = .horizontal
$0.spacing = 5
}
let label = UILabel().with {
$0.text = label
}
formRow.addArrangedSubview(label)
formRow.addArrangedSubview(view)
if let stackView {
stackView.addArrangedSubview(formRow)
} else {
formStackView.addArrangedSubview(formRow)
}
if let pickerViewable = view as? any PickerViewable {
pickerViewable.scrollToBottom = { [weak self] in self?.scrollToBottom() }
}
}
open func setup() {}
open func updateView(viewModel: ModelType) {}
}