vds_ios_sample/VDSSample/ViewControllers/DropShawdowViewController.swift
Matt Bruce e67cdec292 updated dropshadow screen
Signed-off-by: Matt Bruce <matt.bruce@verizon.com>
2024-05-06 19:04:53 -05:00

465 lines
18 KiB
Swift

//
// DropShawdowViewController.swift
// VDSSample
//
// Created by Matt Bruce on 6/13/23.
//
import Foundation
import UIKit
import VDS
import VDSTokens
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 = ShadowView()
var thirdView = ShadowView()
var shadowViews: [ShadowView] {
[component, secondView, thirdView]
}
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(VDSLayout.space2X)
thirdView.pinLeading(VDSLayout.space2X).pinBottom(VDSLayout.space2X)
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?.shadowViews.forEach { $0.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?.shadowViews.forEach { $0.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?.shadowViews.forEach { $0.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?.shadowViews.forEach { $0.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?.shadowViews.forEach { $0.offsetYRange = CGFloat(slider.value) }
self?.updateView()
}).store(in: &subscribers)
//shadow2
showShadow2.publisher(for: .valueChanged).sink(receiveValue: { [weak self] slider in
self?.shadowViews.forEach { $0.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?.shadowViews.forEach { $0.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?.shadowViews.forEach { $0.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?.shadowViews.forEach { $0.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?.shadowViews.forEach { $0.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?.shadowViews.forEach { $0.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.viewLightColor = .paletteYellow53
thirdView.viewLightColor = .paletteBlue46
}
func setupPicker(){
backgroundColorPickerSelectorView.onPickerDidSelect = { [weak self] item in
self?.contentTopView.backgroundColor = item.uiColor
self?.updateView()
}
dropShadowDarkColorPickerSelectorView.onPickerDidSelect = { [weak self] item in
self?.shadowViews.forEach { $0.shadowDarkColor = item }
}
dropShadowLightColorPickerSelectorView.onPickerDidSelect = { [weak self] item in
self?.shadowViews.forEach { $0.shadowLightColor = item }
}
dropShadow2DarkColorPickerSelectorView.onPickerDidSelect = { [weak self] item in
self?.shadowViews.forEach { $0.shadowDarkColor2 = item }
}
dropShadow2LightColorPickerSelectorView.onPickerDidSelect = { [weak self] item in
self?.shadowViews.forEach { $0.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() }}
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() }}
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)
}
public override func updateView() {
super.updateView()
let viewColor = SurfaceColorConfiguration(viewLightColor.uiColor, viewDarkColor.uiColor).getColor(surface)
backgroundColor = viewColor
setNeedsLayout()
layoutIfNeeded()
}
public override var backgroundColor: UIColor? {
didSet {
print("backgroundColor: \(backgroundColor?.hexString ?? "None")")
}
}
public override func layoutSubviews() {
super.layoutSubviews()
layer.cornerRadius = CGFloat(viewRadiusRange)
let dropshadowColor = SurfaceColorConfiguration(shadowLightColor.uiColor, shadowDarkColor.uiColor).getColor(surface)
let dropshadowColor2 = SurfaceColorConfiguration(shadowLightColor2.uiColor, shadowDarkColor2.uiColor).getColor(surface)
var shadowConfigs = [DropShadowConfiguration]()
// Update shadow layers frames to match the view's bounds
if showShadow {
let shadow1Config = VDS.DropShadowConfiguration().with {
$0.shadowRadiusConfiguration = .init(viewRadiusRange, .zero)
$0.shadowColorConfiguration = SurfaceColorConfiguration(dropshadowColor, dropshadowColor).eraseToAnyColorable()
$0.shadowOpacityConfiguration = .init(opacityRange, .zero)
$0.shadowOffsetConfiguration = .init(.init(width: offsetXRange, height: offsetYRange), .zero)
$0.shadowRadiusConfiguration = .init(radiusRange, .zero)
}
shadowConfigs.append(shadow1Config)
}
if showShadow2 {
let shadow2Config = VDS.DropShadowConfiguration().with {
$0.shadowRadiusConfiguration = .init(viewRadiusRange, .zero)
$0.shadowColorConfiguration = SurfaceColorConfiguration(dropshadowColor2, dropshadowColor2).eraseToAnyColorable()
$0.shadowOpacityConfiguration = .init(opacityRange2, .zero)
$0.shadowOffsetConfiguration = .init(.init(width: offsetXRange2, height: offsetYRange2), .zero)
$0.shadowRadiusConfiguration = .init(radiusRange2, .zero)
}
shadowConfigs.append(shadow2Config)
}
if shadowConfigs.count > 0 {
addDropShadows(shadowConfigs)
} else {
removeDropShadows()
}
}
}
extension ViewProtocol where Self: UIView {
private func createShadowLayer() -> CALayer {
let shadowLayer = CALayer()
shadowLayer.backgroundColor = UIColor.clear.cgColor
shadowLayer.frame = bounds
return shadowLayer
}
func addCustomShadow(config: DropShadowConfiguration) {
let shadowLayer = createShadowLayer()
// shadowLayer.shadowColor = config.shadowColorConfiguration.getColor(self).cgColor
// shadowLayer.shadowOpacity = config.shadowOpacityConfiguration.value(for: self)
// shadowLayer.shadowOffset = offset
// shadowLayer.shadowRadius = radius
layer.insertSublayer(shadowLayer, at: 0)
}
func removeAllCustomShadows() {
layer.sublayers?.forEach { sublayer in
if sublayer.shadowOpacity > 0 && sublayer.backgroundColor == UIColor.clear.cgColor {
sublayer.removeFromSuperlayer()
}
}
}
}