422 lines
17 KiB
Swift
422 lines
17 KiB
Swift
//
|
|
// DropShawdowViewController.swift
|
|
// VDSSample
|
|
//
|
|
// Created by Matt Bruce on 6/13/23.
|
|
//
|
|
|
|
import Foundation
|
|
import UIKit
|
|
import VDS
|
|
import VDSColorTokens
|
|
import Combine
|
|
|
|
class DropShadowViewController: BaseViewController<ShadowView> {
|
|
var viewPaddingRange = Slider()
|
|
var viewRadiusRange = Slider()
|
|
var viewSpacerRange = Slider()
|
|
|
|
//shadow 1
|
|
var showShadow = Toggle()
|
|
var opacityRange = Slider()
|
|
var radiusRange = Slider()
|
|
var offsetXRange = Slider()
|
|
var offsetYRange = Slider()
|
|
|
|
//shadow 2
|
|
var showShadow2 = Toggle()
|
|
var opacityRange2 = Slider()
|
|
var radiusRange2 = Slider()
|
|
var offsetXRange2 = Slider()
|
|
var offsetYRange2 = Slider()
|
|
|
|
var viewSize: CGFloat = 100.0
|
|
var componentWrapper: UIView!
|
|
var componentConstraints: NSLayoutConstraint.Container!
|
|
|
|
var secondView = View()
|
|
var thirdView = View()
|
|
|
|
lazy var backgroundColorPickerSelectorView = {
|
|
PickerSelectorView(title: "paletteWhite",
|
|
picker: self.picker,
|
|
items: UIColor.VDSColor.allCases)
|
|
}()
|
|
|
|
lazy var dropShadowLightColorPickerSelectorView = {
|
|
PickerSelectorView(title: "",
|
|
picker: self.picker,
|
|
items: UIColor.VDSColor.allCases)
|
|
}()
|
|
|
|
lazy var dropShadowDarkColorPickerSelectorView = {
|
|
PickerSelectorView(title: "",
|
|
picker: self.picker,
|
|
items: UIColor.VDSColor.allCases)
|
|
}()
|
|
|
|
lazy var dropShadow2LightColorPickerSelectorView = {
|
|
PickerSelectorView(title: "",
|
|
picker: self.picker,
|
|
items: UIColor.VDSColor.allCases)
|
|
}()
|
|
|
|
lazy var dropShadow2DarkColorPickerSelectorView = {
|
|
PickerSelectorView(title: "",
|
|
picker: self.picker,
|
|
items: UIColor.VDSColor.allCases)
|
|
}()
|
|
|
|
lazy var viewLightColorPickerSelectorView = {
|
|
PickerSelectorView(title: "",
|
|
picker: self.picker,
|
|
items: UIColor.VDSColor.allCases)
|
|
}()
|
|
|
|
lazy var viewDarkColorPickerSelectorView = {
|
|
PickerSelectorView(title: "",
|
|
picker: self.picker,
|
|
items: UIColor.VDSColor.allCases)
|
|
}()
|
|
|
|
var spacer: CGFloat = 0 {
|
|
didSet {
|
|
spacings.forEach{ $0.constant = spacer }
|
|
}
|
|
}
|
|
|
|
var viewPadding: CGFloat = 0 {
|
|
didSet {
|
|
componentConstraints.topConstraint?.constant = viewPadding
|
|
componentConstraints.leadingConstraint?.constant = viewPadding
|
|
componentConstraints.trailingConstraint?.constant = -viewPadding
|
|
componentConstraints.bottomConstraint?.constant = -viewPadding
|
|
}
|
|
}
|
|
|
|
var spacings = [NSLayoutConstraint]()
|
|
|
|
override func viewDidLoad() {
|
|
super.viewDidLoad()
|
|
|
|
let label1 = Label().with { $0.text = "View 1"; $0.textAlignment = .center}
|
|
let label2 = Label().with { $0.text = "View 2"; $0.textAlignment = .center}
|
|
let label3 = Label().with { $0.text = "View 3"; $0.textAlignment = .center}
|
|
|
|
component.addSubview(label1)
|
|
label1.pinToSuperView()
|
|
|
|
secondView.addSubview(label2)
|
|
label2.pinToSuperView()
|
|
|
|
thirdView.addSubview(label3)
|
|
label3.pinToSuperView()
|
|
|
|
let wrapper = UIView.makeWrapperWithConstraints(for: component, isTrailing: false)
|
|
componentWrapper = wrapper.view
|
|
componentConstraints = wrapper.container
|
|
|
|
contentTopView.addSubview(secondView)
|
|
contentTopView.addSubview(thirdView)
|
|
contentTopView.addSubview(componentWrapper)
|
|
|
|
component.width(viewSize).height(viewSize)
|
|
secondView.width(viewSize).height(viewSize)
|
|
thirdView.width(viewSize).height(viewSize)
|
|
|
|
componentWrapper.pinTop().pinLeading()
|
|
secondView.pinTop()
|
|
thirdView.pinLeading().pinBottom()
|
|
|
|
secondView.pinTrailingLessThanOrEqualTo(contentTopView.trailingAnchor)
|
|
secondView.pinBottomLessThanOrEqualTo(contentTopView.bottomAnchor)
|
|
thirdView.pinTrailingLessThanOrEqualTo(contentTopView.trailingAnchor)
|
|
|
|
spacings.append(thirdView.pinTop(anchor: componentWrapper.bottomAnchor)!)
|
|
spacings.append(secondView.pinLeading(anchor: componentWrapper.trailingAnchor)!)
|
|
|
|
viewPadding = 10
|
|
spacer = 10
|
|
|
|
component.setNeedsUpdate()
|
|
|
|
setupPicker()
|
|
setupModel()
|
|
updateView()
|
|
}
|
|
|
|
override func showDebug(show: Bool) {
|
|
super.showDebug(show: show)
|
|
component.debugBorder(show: false)
|
|
componentWrapper.debugBorder(show: show, color: .green)
|
|
secondView.debugBorder(show: show, color: .green)
|
|
thirdView.debugBorder(show: show, color: .green)
|
|
}
|
|
|
|
override func setupForm(){
|
|
super.setupForm()
|
|
formStackView.title = "Screen Settings"
|
|
addFormRow(label: "Background Color", view: backgroundColorPickerSelectorView)
|
|
addFormRow(label: "Space Between 1,2,3", view: viewSpacerRange)
|
|
|
|
let form1 = FormSection()
|
|
form1.title = "View 1 Settings"
|
|
form1.addFormRow(label: "All ", view: viewPaddingRange)
|
|
form1.addFormRow(label: "Padding", view: viewPaddingRange)
|
|
form1.addFormRow(label: "Corner Radius", view: viewRadiusRange)
|
|
form1.addFormRow(label: "Light", view: viewLightColorPickerSelectorView)
|
|
form1.addFormRow(label: "Dark", view: viewDarkColorPickerSelectorView)
|
|
|
|
let form2 = FormSection()
|
|
form2.title = "View 1 Shadow Settings"
|
|
form2.addFormRow(label: "Show", view: .makeWrapper(for: showShadow))
|
|
form2.addFormRow(label: "Shawdow Light", view: dropShadowLightColorPickerSelectorView)
|
|
form2.addFormRow(label: "Shawdow Dark", view: dropShadowDarkColorPickerSelectorView)
|
|
form2.addFormRow(label: "Radius (Blur)", view: radiusRange)
|
|
form2.addFormRow(label: "Width (OffSet X)", view: offsetXRange)
|
|
form2.addFormRow(label: "Height (Offset Y)", view: offsetYRange)
|
|
form2.addFormRow(label: "Opacity", view: opacityRange)
|
|
|
|
let form3 = FormSection()
|
|
form3.title = "View 1 Shadow 2 Settings"
|
|
form3.addFormRow(label: "Show", view: .makeWrapper(for: showShadow2))
|
|
form3.addFormRow(label: "Shawdow Light", view: dropShadow2LightColorPickerSelectorView)
|
|
form3.addFormRow(label: "Shawdow Dark", view: dropShadow2DarkColorPickerSelectorView)
|
|
form3.addFormRow(label: "Radius (Blur)", view: radiusRange2)
|
|
form3.addFormRow(label: "Width (OffSet X)", view: offsetXRange2)
|
|
form3.addFormRow(label: "Height (Offset Y)", view: offsetYRange2)
|
|
form3.addFormRow(label: "Opacity", view: opacityRange2)
|
|
|
|
|
|
append(section: form1)
|
|
append(section: form2)
|
|
append(section: form3)
|
|
|
|
//shadow1
|
|
showShadow.publisher(for: .valueChanged).sink(receiveValue: { [weak self] slider in
|
|
self?.component.showShadow = slider.isOn
|
|
self?.updateView()
|
|
}).store(in: &subscribers)
|
|
|
|
opacityRange.maximumValue = 1.0
|
|
opacityRange.minimumValue = 0.0
|
|
opacityRange.value = 1.0
|
|
opacityRange.publisher(for: .valueChanged).sink(receiveValue: { [weak self] slider in
|
|
self?.component.opacityRange = CGFloat(slider.value)
|
|
self?.updateView()
|
|
}).store(in: &subscribers)
|
|
|
|
radiusRange.maximumValue = 20.0
|
|
radiusRange.minimumValue = 0.0
|
|
radiusRange.value = 2.0
|
|
radiusRange.publisher(for: .valueChanged).sink(receiveValue: { [weak self] slider in
|
|
self?.component.radiusRange = CGFloat(slider.value)
|
|
self?.updateView()
|
|
}).store(in: &subscribers)
|
|
|
|
offsetXRange.maximumValue = 20
|
|
offsetXRange.minimumValue = -20
|
|
offsetXRange.value = 2.0
|
|
offsetXRange.publisher(for: .valueChanged).sink(receiveValue: { [weak self] slider in
|
|
self?.component.offsetXRange = CGFloat(slider.value)
|
|
self?.updateView()
|
|
}).store(in: &subscribers)
|
|
|
|
offsetYRange.maximumValue = 20
|
|
offsetYRange.minimumValue = -20
|
|
offsetYRange.value = 2.0
|
|
offsetYRange.publisher(for: .valueChanged).sink(receiveValue: { [weak self] slider in
|
|
self?.component.offsetYRange = CGFloat(slider.value)
|
|
self?.updateView()
|
|
}).store(in: &subscribers)
|
|
|
|
//shadow2
|
|
showShadow2.publisher(for: .valueChanged).sink(receiveValue: { [weak self] slider in
|
|
self?.component.showShadow2 = slider.isOn
|
|
self?.updateView()
|
|
}).store(in: &subscribers)
|
|
|
|
opacityRange2.maximumValue = 1.0
|
|
opacityRange2.minimumValue = 0.0
|
|
opacityRange2.value = 1.0
|
|
opacityRange2.publisher(for: .valueChanged).sink(receiveValue: { [weak self] slider in
|
|
self?.component.opacityRange2 = CGFloat(slider.value)
|
|
self?.updateView()
|
|
}).store(in: &subscribers)
|
|
|
|
radiusRange2.maximumValue = 20.0
|
|
radiusRange2.minimumValue = 0.0
|
|
radiusRange2.value = 2.0
|
|
radiusRange2.publisher(for: .valueChanged).sink(receiveValue: { [weak self] slider in
|
|
self?.component.radiusRange2 = CGFloat(slider.value)
|
|
self?.updateView()
|
|
}).store(in: &subscribers)
|
|
|
|
offsetXRange2.maximumValue = 20
|
|
offsetXRange2.minimumValue = -20
|
|
offsetXRange2.value = 2.0
|
|
offsetXRange2.publisher(for: .valueChanged).sink(receiveValue: { [weak self] slider in
|
|
self?.component.offsetXRange2 = CGFloat(slider.value)
|
|
self?.updateView()
|
|
}).store(in: &subscribers)
|
|
|
|
offsetYRange2.maximumValue = 20
|
|
offsetYRange2.minimumValue = -20
|
|
offsetYRange2.value = 2.0
|
|
offsetYRange2.publisher(for: .valueChanged).sink(receiveValue: { [weak self] slider in
|
|
self?.component.offsetYRange2 = CGFloat(slider.value)
|
|
self?.updateView()
|
|
}).store(in: &subscribers)
|
|
|
|
//view
|
|
viewPaddingRange.maximumValue = 50.0
|
|
viewPaddingRange.minimumValue = 0.0
|
|
viewPaddingRange.value = 2.0
|
|
viewPaddingRange.publisher(for: .valueChanged).sink(receiveValue: { [weak self] slider in
|
|
self?.viewPadding = CGFloat(slider.value)
|
|
self?.updateView()
|
|
}).store(in: &subscribers)
|
|
|
|
viewRadiusRange.maximumValue = Float(viewSize / 2)
|
|
viewRadiusRange.minimumValue = 0
|
|
viewRadiusRange.value = 8.0
|
|
viewRadiusRange.publisher(for: .valueChanged).sink(receiveValue: { [weak self] slider in
|
|
self?.component.viewRadiusRange = CGFloat(slider.value)
|
|
self?.updateView()
|
|
}).store(in: &subscribers)
|
|
|
|
viewSpacerRange.maximumValue = 50
|
|
viewSpacerRange.minimumValue = 0
|
|
viewSpacerRange.value = 10.0
|
|
viewSpacerRange.publisher(for: .valueChanged).sink(receiveValue: { [weak self] slider in
|
|
self?.spacer = CGFloat(slider.value)
|
|
}).store(in: &subscribers)
|
|
|
|
dropShadowLightColorPickerSelectorView.text = component.shadowLightColor.rawValue
|
|
dropShadowDarkColorPickerSelectorView.text = component.shadowDarkColor.rawValue
|
|
dropShadow2LightColorPickerSelectorView.text = component.shadowLightColor2.rawValue
|
|
dropShadow2DarkColorPickerSelectorView.text = component.shadowDarkColor2.rawValue
|
|
viewLightColorPickerSelectorView.text = component.viewLightColor.rawValue
|
|
viewDarkColorPickerSelectorView.text = component.viewDarkColor.rawValue
|
|
|
|
showShadow.isOn = component.showShadow
|
|
showShadow2.isOn = component.showShadow2
|
|
}
|
|
|
|
func setupModel() {
|
|
//setup UI
|
|
|
|
|
|
}
|
|
|
|
override func updateView() {
|
|
secondView.backgroundColor = .red
|
|
thirdView.backgroundColor = .purple
|
|
}
|
|
|
|
func setupPicker(){
|
|
|
|
backgroundColorPickerSelectorView.onPickerDidSelect = { [weak self] item in
|
|
self?.contentTopView.backgroundColor = item.uiColor
|
|
self?.updateView()
|
|
}
|
|
|
|
dropShadowDarkColorPickerSelectorView.onPickerDidSelect = { [weak self] item in
|
|
self?.component.shadowDarkColor = item
|
|
}
|
|
|
|
dropShadowLightColorPickerSelectorView.onPickerDidSelect = { [weak self] item in
|
|
self?.component.shadowLightColor = item
|
|
}
|
|
|
|
dropShadow2DarkColorPickerSelectorView.onPickerDidSelect = { [weak self] item in
|
|
self?.component.shadowDarkColor2 = item
|
|
}
|
|
|
|
dropShadow2LightColorPickerSelectorView.onPickerDidSelect = { [weak self] item in
|
|
self?.component.shadowLightColor2 = item
|
|
}
|
|
viewLightColorPickerSelectorView.onPickerDidSelect = { [weak self] item in
|
|
self?.component.viewLightColor = item
|
|
}
|
|
|
|
viewDarkColorPickerSelectorView.onPickerDidSelect = { [weak self] item in
|
|
self?.component.viewDarkColor = item
|
|
}
|
|
}
|
|
}
|
|
|
|
public class ShadowView: View {
|
|
|
|
public var viewLightColor: UIColor.VDSColor = .paletteGray65 { didSet { setNeedsUpdate() }}
|
|
public var viewDarkColor: UIColor.VDSColor = .backgroundPrimaryLight { didSet { setNeedsUpdate() }}
|
|
|
|
public var viewRadiusRange: CGFloat = 8.0 { didSet { setNeedsUpdate() }}
|
|
|
|
private var shadowLayer1: CALayer = CALayer()
|
|
public var showShadow: Bool = true { didSet { setNeedsUpdate() }}
|
|
public var opacityRange: CGFloat = 1.0 { didSet { setNeedsUpdate() }}
|
|
public var offsetXRange: CGFloat = 2.0 { didSet { setNeedsUpdate() }}
|
|
public var offsetYRange: CGFloat = 2.0 { didSet { setNeedsUpdate() }}
|
|
public var radiusRange: CGFloat = 2.0 { didSet { setNeedsUpdate() }}
|
|
public var shadowLightColor: UIColor.VDSColor = .backgroundPrimaryDark { didSet { setNeedsUpdate() }}
|
|
public var shadowDarkColor: UIColor.VDSColor = .backgroundPrimaryLight { didSet { setNeedsUpdate() }}
|
|
|
|
private var shadowLayer2: CALayer = CALayer()
|
|
public var showShadow2: Bool = false { didSet { setNeedsUpdate() }}
|
|
public var opacityRange2: CGFloat = 1.0 { didSet { setNeedsUpdate() }}
|
|
public var offsetXRange2: CGFloat = 2.0 { didSet { setNeedsUpdate() }}
|
|
public var offsetYRange2: CGFloat = 2.0 { didSet { setNeedsUpdate() }}
|
|
public var radiusRange2: CGFloat = 2.0 { didSet { setNeedsUpdate() }}
|
|
public var shadowLightColor2: UIColor.VDSColor = .backgroundPrimaryDark { didSet { setNeedsUpdate() }}
|
|
public var shadowDarkColor2: UIColor.VDSColor = .backgroundPrimaryLight { didSet { setNeedsUpdate() }}
|
|
|
|
public override func setup() {
|
|
super.setup()
|
|
width(constant: 100)
|
|
height(constant: 100)
|
|
|
|
// Add shadow layers as sublayers of the view's layer
|
|
layer.insertSublayer(shadowLayer1, at: 0)
|
|
layer.insertSublayer(shadowLayer2, at: 0)
|
|
}
|
|
|
|
public override func updateView() {
|
|
super.updateView()
|
|
let viewColor = SurfaceColorConfiguration(viewLightColor.uiColor, viewDarkColor.uiColor).getColor(surface)
|
|
backgroundColor = viewColor
|
|
shadowLayer1.backgroundColor = viewColor.cgColor
|
|
shadowLayer2.backgroundColor = viewColor.cgColor
|
|
shadowLayer1.isHidden = !showShadow
|
|
shadowLayer2.isHidden = !showShadow2
|
|
setNeedsLayout()
|
|
layoutIfNeeded()
|
|
}
|
|
|
|
|
|
public override func layoutSubviews() {
|
|
super.layoutSubviews()
|
|
|
|
let dropshadowColor = SurfaceColorConfiguration(shadowLightColor.uiColor, shadowDarkColor.uiColor).getColor(surface)
|
|
let dropshadowColor2 = SurfaceColorConfiguration(shadowLightColor2.uiColor, shadowDarkColor2.uiColor).getColor(surface)
|
|
layer.cornerRadius = CGFloat(viewRadiusRange)
|
|
layer.masksToBounds = false
|
|
|
|
// Update shadow layers frames to match the view's bounds
|
|
shadowLayer1.frame = bounds
|
|
shadowLayer2.frame = bounds
|
|
|
|
shadowLayer1.cornerRadius = CGFloat(viewRadiusRange)
|
|
shadowLayer1.shadowColor = dropshadowColor.cgColor
|
|
shadowLayer1.shadowOpacity = Float(opacityRange)
|
|
shadowLayer1.shadowOffset = .init(width: CGFloat(offsetXRange), height: CGFloat(offsetYRange))
|
|
shadowLayer1.shadowRadius = CGFloat(radiusRange)
|
|
|
|
shadowLayer2.cornerRadius = CGFloat(viewRadiusRange)
|
|
shadowLayer2.shadowColor = dropshadowColor2.cgColor
|
|
shadowLayer2.shadowOpacity = Float(opacityRange2)
|
|
shadowLayer2.shadowOffset = .init(width: CGFloat(offsetXRange2), height: CGFloat(offsetYRange2))
|
|
shadowLayer2.shadowRadius = CGFloat(radiusRange2)
|
|
}
|
|
}
|