304 lines
9.8 KiB
Swift
304 lines
9.8 KiB
Swift
//
|
|
// TileContainer.swift
|
|
// VDS
|
|
//
|
|
// Created by Matt Bruce on 12/16/22.
|
|
//
|
|
|
|
import Foundation
|
|
import VDSColorTokens
|
|
import UIKit
|
|
|
|
@objc(VDSTileContainer)
|
|
open class TileContainer: Control {
|
|
|
|
//--------------------------------------------------
|
|
// MARK: - Initializers
|
|
//--------------------------------------------------
|
|
required public init() {
|
|
super.init(frame: .zero)
|
|
initialSetup()
|
|
}
|
|
|
|
public override init(frame: CGRect) {
|
|
super.init(frame: .zero)
|
|
initialSetup()
|
|
}
|
|
|
|
public required init?(coder: NSCoder) {
|
|
super.init(coder: coder)
|
|
initialSetup()
|
|
}
|
|
|
|
public enum ContainerBackgroundColor: String, CaseIterable {
|
|
case white
|
|
case black
|
|
case gray
|
|
case transparent
|
|
}
|
|
|
|
public enum ContainerPadding: String, CaseIterable {
|
|
case twelve = "12"
|
|
case sixteen = "16"
|
|
case twentyFour = "24"
|
|
case thirtyTwo = "32"
|
|
case fourtyEight = "48"
|
|
}
|
|
|
|
public enum ContainerScalingType: String, CaseIterable {
|
|
case ratio1x1 = "1:1"
|
|
case ratio3x4 = "3:4"
|
|
case ratio4x3 = "4:3"
|
|
case ratio2x3 = "2:3"
|
|
case ratio3x2 = "3:2"
|
|
case ratio9x16 = "9:16"
|
|
case ratio16x9 = "16:9"
|
|
case ratio1x2 = "1:2"
|
|
case ratio2x1 = "2:1"
|
|
case none
|
|
}
|
|
|
|
//--------------------------------------------------
|
|
// MARK: - Public Properties
|
|
//--------------------------------------------------
|
|
public var backgroundImage: UIImage? { didSet{ didChange() } }
|
|
|
|
public var containerView = View()
|
|
|
|
public var highlightView = View()
|
|
|
|
public var containerBackgroundColor: ContainerBackgroundColor = .white { didSet{ didChange() } }
|
|
|
|
public var containerPadding: ContainerPadding = .sixteen { didSet{ didChange() } }
|
|
|
|
public var aspectRatio: ContainerScalingType = .ratio1x1 { didSet{ didChange() } }
|
|
|
|
public var imageFallbackColor: Surface = .light { didSet{ didChange() } }
|
|
|
|
private var _width: CGFloat = 100
|
|
public var width: CGFloat {
|
|
get { return _width }
|
|
set {
|
|
if newValue > 100 {
|
|
_width = newValue
|
|
didChange()
|
|
}
|
|
}
|
|
}
|
|
|
|
public var height: CGFloat? { didSet{ didChange() } }
|
|
|
|
public var showBorder: Bool = false { didSet{ didChange() } }
|
|
|
|
public var showDropShadows: Bool = false { didSet{ didChange() } }
|
|
|
|
//--------------------------------------------------
|
|
// MARK: - Private Properties
|
|
//--------------------------------------------------
|
|
private var backgroundImageView = UIImageView().with {
|
|
$0.translatesAutoresizingMaskIntoConstraints = false
|
|
$0.contentMode = .scaleAspectFill
|
|
$0.clipsToBounds = true
|
|
}
|
|
|
|
internal var padding: CGFloat {
|
|
switch containerPadding {
|
|
case .twelve:
|
|
return 12.0
|
|
case .sixteen:
|
|
return 16.0
|
|
case .twentyFour:
|
|
return 24.0
|
|
case .thirtyTwo:
|
|
return 32.0
|
|
case .fourtyEight:
|
|
return 48.0
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------
|
|
// MARK: - Constraints
|
|
//--------------------------------------------------
|
|
internal var widthConstraint: NSLayoutConstraint?
|
|
internal var heightConstraint: NSLayoutConstraint?
|
|
internal var heightGreaterThanConstraint: NSLayoutConstraint?
|
|
internal var containerTopConstraint: NSLayoutConstraint?
|
|
internal var containerBottomConstraint: NSLayoutConstraint?
|
|
internal var containerLeadingConstraint: NSLayoutConstraint?
|
|
internal var containerTrailingConstraint: NSLayoutConstraint?
|
|
|
|
//functions
|
|
//--------------------------------------------------
|
|
// MARK: - Lifecycle
|
|
//--------------------------------------------------
|
|
|
|
open override func setup() {
|
|
super.setup()
|
|
addSubview(backgroundImageView)
|
|
addSubview(containerView)
|
|
addSubview(highlightView)
|
|
|
|
widthConstraint = widthAnchor.constraint(equalToConstant: width)
|
|
widthConstraint?.isActive = true
|
|
|
|
heightGreaterThanConstraint = heightAnchor.constraint(greaterThanOrEqualToConstant: 44.0)
|
|
heightGreaterThanConstraint?.isActive = false
|
|
|
|
heightConstraint = heightAnchor.constraint(equalToConstant: width)
|
|
heightConstraint?.isActive = true
|
|
|
|
backgroundImageView.pinToSuperView()
|
|
backgroundImageView.isUserInteractionEnabled = false
|
|
backgroundImageView.isHidden = true
|
|
|
|
containerView.isUserInteractionEnabled = false
|
|
containerView.backgroundColor = .clear
|
|
|
|
containerTopConstraint = containerView.topAnchor.constraint(lessThanOrEqualTo: topAnchor, constant: padding)
|
|
containerTopConstraint?.isActive = true
|
|
containerBottomConstraint = containerView.bottomAnchor.constraint(lessThanOrEqualTo: bottomAnchor, constant: padding)
|
|
containerBottomConstraint?.isActive = true
|
|
containerLeadingConstraint = containerView.leadingAnchor.constraint(lessThanOrEqualTo: leadingAnchor, constant: padding)
|
|
containerLeadingConstraint?.isActive = true
|
|
containerTrailingConstraint = containerView.trailingAnchor.constraint(lessThanOrEqualTo: trailingAnchor, constant: padding)
|
|
containerTrailingConstraint?.isActive = true
|
|
|
|
highlightView.pinToSuperView()
|
|
highlightView.isUserInteractionEnabled = false
|
|
highlightView.isHidden = true
|
|
highlightView.backgroundColor = .clear
|
|
|
|
//corner radius
|
|
layer.cornerRadius = cornerRadius
|
|
backgroundImageView.layer.cornerRadius = 8
|
|
highlightView.layer.cornerRadius = 8
|
|
|
|
}
|
|
|
|
public override func reset() {
|
|
super.reset()
|
|
|
|
}
|
|
|
|
//--------------------------------------------------
|
|
// MARK: - Configuration
|
|
//--------------------------------------------------
|
|
private let cornerRadius = 8.0
|
|
|
|
private var backgroundColorConfig = BackgroundColorConfiguration()
|
|
|
|
private var borderColorConfig = SurfaceColorConfiguration().with {
|
|
$0.lightColor = VDSColor.elementsLowContrastOnLight
|
|
$0.darkColor = VDSColor.elementsLowContrastOnDark
|
|
}
|
|
|
|
private var imageFallbackColorConfig = SurfaceColorConfiguration().with {
|
|
$0.lightColor = VDSColor.backgroundPrimaryLight
|
|
$0.darkColor = VDSColor.backgroundPrimaryDark
|
|
}
|
|
|
|
private var hightLightViewColorConfig = SurfaceColorConfiguration().with {
|
|
$0.lightColor = VDSColor.paletteWhite.withAlphaComponent(0.3)
|
|
$0.darkColor = VDSColor.paletteBlack.withAlphaComponent(0.3)
|
|
}
|
|
|
|
//--------------------------------------------------
|
|
// MARK: - State
|
|
//--------------------------------------------------
|
|
var ratioSize: CGSize {
|
|
var height: CGFloat = width
|
|
|
|
switch aspectRatio {
|
|
case .ratio1x1:
|
|
break;
|
|
case .ratio3x4:
|
|
height = (4 / 3) * width
|
|
case .ratio4x3:
|
|
height = (3 / 4) * width
|
|
case .ratio2x3:
|
|
height = (3 / 2) * width
|
|
case .ratio3x2:
|
|
height = (2 / 3) * width
|
|
case .ratio9x16:
|
|
height = (16 / 9) * width
|
|
case .ratio16x9:
|
|
height = (9 / 16) * width
|
|
case .ratio1x2:
|
|
height = (2 / 1) * width
|
|
case .ratio2x1:
|
|
height = (1 / 2) * width
|
|
|
|
default:
|
|
break
|
|
}
|
|
|
|
return CGSize(width: width, height: height)
|
|
}
|
|
|
|
open override func updateView() {
|
|
super.updateView()
|
|
|
|
highlightView.backgroundColor = hightLightViewColorConfig.getColor(self)
|
|
highlightView.isHidden = !isHighlighted
|
|
|
|
if let backgroundImage {
|
|
backgroundImageView.image = backgroundImage
|
|
backgroundImageView.isHidden = false
|
|
backgroundColor = imageFallbackColorConfig.getColor(self)
|
|
} else {
|
|
backgroundImageView.isHidden = true
|
|
backgroundColor = backgroundColorConfig.getColor(self)
|
|
}
|
|
|
|
layer.borderColor = borderColorConfig.getColor(self).cgColor
|
|
layer.borderWidth = showBorder ? 1 : 0
|
|
|
|
containerTopConstraint?.constant = padding
|
|
containerLeadingConstraint?.constant = padding
|
|
containerBottomConstraint?.constant = -padding
|
|
containerTrailingConstraint?.constant = -padding
|
|
|
|
if aspectRatio == .none {
|
|
widthConstraint?.constant = width
|
|
heightConstraint?.isActive = false
|
|
heightGreaterThanConstraint?.isActive = true
|
|
} else if let height {
|
|
widthConstraint?.constant = width
|
|
heightConstraint?.constant = height
|
|
heightConstraint?.isActive = true
|
|
heightGreaterThanConstraint?.isActive = false
|
|
} else {
|
|
let size = ratioSize
|
|
widthConstraint?.constant = size.width
|
|
heightConstraint?.constant = size.height
|
|
heightConstraint?.isActive = true
|
|
heightGreaterThanConstraint?.isActive = false
|
|
}
|
|
}
|
|
|
|
public func addContentView(_ view: UIView) {
|
|
containerView.addSubview(view)
|
|
view.pinToSuperView()
|
|
}
|
|
|
|
class BackgroundColorConfiguration: ObjectColorable {
|
|
typealias ObjectType = TileContainer
|
|
|
|
required init() { }
|
|
|
|
func getColor(_ object: TileContainer) -> UIColor {
|
|
switch object.containerBackgroundColor {
|
|
|
|
case .white:
|
|
return VDSColor.backgroundPrimaryLight
|
|
case .black:
|
|
return VDSColor.backgroundPrimaryDark
|
|
case .gray:
|
|
return VDSColor.backgroundSecondaryLight
|
|
case .transparent:
|
|
return UIColor.clear
|
|
}
|
|
}
|
|
}
|
|
}
|