206 lines
7.9 KiB
Swift
206 lines
7.9 KiB
Swift
//
|
|
// CommonControllerModal.swift
|
|
// Wallet
|
|
//
|
|
// Created by Igor on 9.02.2021.
|
|
//
|
|
|
|
import UIKit
|
|
|
|
extension UIViewController {
|
|
private struct Values {
|
|
static var image = "image"
|
|
static var text = "text"
|
|
}
|
|
@IBInspectable var image: UIImage? {
|
|
get { Common.Runtime.object(self, key: &Values.image) }
|
|
set { Common.Runtime.set(self, value: newValue, key: &Values.image) }
|
|
}
|
|
@IBInspectable var text: String? {
|
|
get { Common.Runtime.object(self, key: &Values.text) }
|
|
set { Common.Runtime.set(self, value: newValue, key: &Values.text) }
|
|
}
|
|
}
|
|
|
|
class CommonControllerPopup: UIViewController {
|
|
|
|
@IBOutlet weak var contentView: UIView!
|
|
@IBOutlet private weak var alphaView: UIView!
|
|
@IBOutlet private weak var stackView: UIStackView!
|
|
@IBOutlet private weak var offset: NSLayoutConstraint!
|
|
@IBOutlet weak var bottomHeight: NSLayoutConstraint!
|
|
@IBOutlet private weak var titleLbl: UILabel!
|
|
@IBOutlet private weak var textLbl: UILabel!
|
|
@IBOutlet private weak var imgView: UIImageView!
|
|
@IBOutlet private weak var imgViewWidth: NSLayoutConstraint!
|
|
@IBOutlet private weak var imgViewHeight: NSLayoutConstraint!
|
|
@IBOutlet private weak var contentLeft: NSLayoutConstraint!
|
|
@IBOutlet private weak var contentWidth: NSLayoutConstraint!
|
|
@IBOutlet private weak var contentRight: NSLayoutConstraint!
|
|
@IBOutlet private weak var contentScrollVew: UIScrollView!
|
|
@IBOutlet private weak var contentStackView: UIStackView!
|
|
@IBOutlet private weak var contentOffsetView: UIView!
|
|
|
|
private let contentViewController: UIViewController?
|
|
private var willPresent = true
|
|
private let completion: (() -> Void)?
|
|
private let contentScrollIsEnabled: Bool
|
|
|
|
init(contentViewController: UIViewController, contentScrollIsEnabled: Bool, completion: (() -> Void)? = nil) {
|
|
contentViewController.view.backgroundColor = .clear
|
|
self.completion = completion
|
|
self.contentScrollIsEnabled = contentScrollIsEnabled
|
|
self.contentViewController = contentViewController
|
|
super.init(nibName: "CommonControllerPopup", bundle: nil)
|
|
_ = view
|
|
modalPresentationStyle = .custom
|
|
transitioningDelegate = self
|
|
addChild(contentViewController)
|
|
alphaView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(onHide)))
|
|
stackView.superview?.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(onPan(_:))))
|
|
contentStackView.addArrangedSubview(contentViewController.view)
|
|
update()
|
|
}
|
|
|
|
init(
|
|
image: UIImage? = nil,
|
|
title: String? = nil,
|
|
text: String? = nil,
|
|
views: [UIView],
|
|
spacing: CGFloat,
|
|
completion: (() -> Void)? = nil
|
|
) {
|
|
contentViewController = nil
|
|
self.contentScrollIsEnabled = true
|
|
self.completion = completion
|
|
super.init(nibName: "CommonControllerPopup", bundle: nil)
|
|
_ = view
|
|
self.title = title
|
|
self.text = text
|
|
self.image = image
|
|
modalPresentationStyle = .custom
|
|
transitioningDelegate = self
|
|
alphaView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(onHide)))
|
|
stackView.superview?.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(onPan(_:))))
|
|
views.forEach({ contentStackView.addArrangedSubview($0) })
|
|
contentLeft.constant = 12
|
|
contentWidth.constant = -24
|
|
contentRight.constant = 12
|
|
contentStackView.spacing = spacing
|
|
update()
|
|
}
|
|
|
|
required init?(coder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
override func viewDidLayoutSubviews() {
|
|
super.viewDidLayoutSubviews()
|
|
contentScrollVew.isScrollEnabled = self.contentScrollIsEnabled ? self.contentScrollVew.frame.height < contentStackView.frame.height : false
|
|
}
|
|
|
|
private func update() {
|
|
if let image = contentViewController?.image ?? image {
|
|
imgView.image = image
|
|
imgViewWidth.constant = image.size.width
|
|
imgViewHeight.constant = image.size.height
|
|
imgView.superview?.isHidden = false
|
|
} else {
|
|
imgView.superview?.isHidden = true
|
|
}
|
|
if let title = contentViewController?.title ?? title {
|
|
titleLbl.superview?.isHidden = false
|
|
titleLbl.attributedText = title.localized.attributed(style: .bold, size: 28, color: Asset.textCoal.color)
|
|
} else {
|
|
titleLbl.superview?.isHidden = true
|
|
}
|
|
if let text = contentViewController?.text ?? text {
|
|
textLbl.superview?.isHidden = false
|
|
textLbl.attributedText = text.localized.attributed(style: .regular, size: 14, color: Asset.textGranite.color)
|
|
} else {
|
|
textLbl.superview?.isHidden = true
|
|
}
|
|
contentOffsetView.isHidden = (titleLbl.attributedText?.string.isEmpty ?? true) && (textLbl.attributedText?.string.isEmpty ?? true)
|
|
stackView.layoutIfNeeded()
|
|
view.frame = UIScreen.main.bounds
|
|
view.layoutIfNeeded()
|
|
}
|
|
|
|
override func viewWillDisappear(_ animated: Bool) {
|
|
super.viewWillDisappear(animated)
|
|
completion?()
|
|
}
|
|
|
|
override func viewWillAppear(_ animated: Bool) {
|
|
super.viewWillAppear(animated)
|
|
Alert.refresh()
|
|
}
|
|
|
|
@objc private func onHide() {
|
|
dismiss(animated: true)
|
|
}
|
|
|
|
private var point: CGPoint!
|
|
|
|
@objc private func onPan(_ pan: UIPanGestureRecognizer) {
|
|
switch pan.state {
|
|
case .began:
|
|
point = pan.location(in: view)
|
|
case .changed:
|
|
let new = pan.location(in: view)
|
|
offset.constant += point.y - new.y
|
|
if offset.constant > -bottomHeight.constant {
|
|
offset.constant = -bottomHeight.constant
|
|
}
|
|
view.layoutIfNeeded()
|
|
point = new
|
|
case .ended, .cancelled:
|
|
if offset.constant < -stackView.frame.height/2 {
|
|
dismiss(animated: true)
|
|
} else {
|
|
offset.constant = -bottomHeight.constant
|
|
UIView.animate(withDuration: Animation.medium) { self.view.layoutIfNeeded() }
|
|
}
|
|
default: break
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
extension CommonControllerPopup: UIViewControllerTransitioningDelegate {
|
|
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
|
|
willPresent = false
|
|
return self
|
|
}
|
|
func animationController(
|
|
forPresented presented: UIViewController,
|
|
presenting: UIViewController,
|
|
source: UIViewController
|
|
) -> UIViewControllerAnimatedTransitioning? { self }
|
|
}
|
|
|
|
extension CommonControllerPopup: UIViewControllerAnimatedTransitioning {
|
|
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { 0.2 }
|
|
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
|
|
let presentView = willPresent ? transitionContext.viewController(forKey: .to)!.view! : transitionContext.viewController(forKey: .from)!.view!
|
|
if willPresent {
|
|
transitionContext.containerView.addSubview(presentView)
|
|
offset.constant = -stackView.frame.height
|
|
view.layoutIfNeeded()
|
|
}
|
|
presentView.frame = view.bounds
|
|
alphaView.alpha = willPresent ? 0 : 1
|
|
offset.constant = willPresent ? -bottomHeight.constant : -stackView.frame.height
|
|
|
|
UIView.animate(withDuration: transitionDuration(using: transitionContext), animations: {
|
|
self.alphaView.alpha = self.willPresent ? 1 : 0
|
|
self.view.layoutIfNeeded()
|
|
}, completion: { (success) in
|
|
if !self.willPresent {
|
|
presentView.removeFromSuperview()
|
|
}
|
|
transitionContext.completeTransition(success)
|
|
})
|
|
}
|
|
}
|