TileContainer VDS changes

This commit is contained in:
Bandaru, Krishna Kishore 2024-02-21 21:04:51 +00:00 committed by Bruce, Matt R
parent e6f9b96f5f
commit 8b3eb632a8
5 changed files with 258 additions and 51 deletions

View File

@ -14,6 +14,8 @@
44604AD729CE196600E62B51 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44604AD629CE196600E62B51 /* Line.swift */; }; 44604AD729CE196600E62B51 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44604AD629CE196600E62B51 /* Line.swift */; };
5F21D7BF28DCEB3D003E7CD6 /* Useable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F21D7BE28DCEB3D003E7CD6 /* Useable.swift */; }; 5F21D7BF28DCEB3D003E7CD6 /* Useable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F21D7BE28DCEB3D003E7CD6 /* Useable.swift */; };
5FC35BE328D51405004EBEAC /* Button.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FC35BE228D51405004EBEAC /* Button.swift */; }; 5FC35BE328D51405004EBEAC /* Button.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FC35BE228D51405004EBEAC /* Button.swift */; };
7115BD3C2B84C0C200E0A610 /* TileContainerChangeLog.txt in Resources */ = {isa = PBXBuildFile; fileRef = 7115BD3B2B84C0C200E0A610 /* TileContainerChangeLog.txt */; };
71BFA70A2B7F70E6000DCE33 /* Dropshadowable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71BFA7092B7F70E6000DCE33 /* Dropshadowable.swift */; };
71C02B382B7BD98F00E93E66 /* NotificationChangeLog.txt in Resources */ = {isa = PBXBuildFile; fileRef = 71C02B372B7BD98F00E93E66 /* NotificationChangeLog.txt */; }; 71C02B382B7BD98F00E93E66 /* NotificationChangeLog.txt in Resources */ = {isa = PBXBuildFile; fileRef = 71C02B372B7BD98F00E93E66 /* NotificationChangeLog.txt */; };
EA0B18022A9E236900F2D0CD /* SelectorGroupBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA0B18012A9E236900F2D0CD /* SelectorGroupBase.swift */; }; EA0B18022A9E236900F2D0CD /* SelectorGroupBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA0B18012A9E236900F2D0CD /* SelectorGroupBase.swift */; };
EA0B18052A9E2D2D00F2D0CD /* SelectorBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA0B18032A9E2D2D00F2D0CD /* SelectorBase.swift */; }; EA0B18052A9E2D2D00F2D0CD /* SelectorBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA0B18032A9E2D2D00F2D0CD /* SelectorBase.swift */; };
@ -178,6 +180,8 @@
44604AD629CE196600E62B51 /* Line.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Line.swift; sourceTree = "<group>"; }; 44604AD629CE196600E62B51 /* Line.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Line.swift; sourceTree = "<group>"; };
5F21D7BE28DCEB3D003E7CD6 /* Useable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Useable.swift; sourceTree = "<group>"; }; 5F21D7BE28DCEB3D003E7CD6 /* Useable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Useable.swift; sourceTree = "<group>"; };
5FC35BE228D51405004EBEAC /* Button.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Button.swift; sourceTree = "<group>"; }; 5FC35BE228D51405004EBEAC /* Button.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Button.swift; sourceTree = "<group>"; };
7115BD3B2B84C0C200E0A610 /* TileContainerChangeLog.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = TileContainerChangeLog.txt; sourceTree = "<group>"; };
71BFA7092B7F70E6000DCE33 /* Dropshadowable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Dropshadowable.swift; sourceTree = "<group>"; };
71C02B372B7BD98F00E93E66 /* NotificationChangeLog.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = NotificationChangeLog.txt; sourceTree = "<group>"; }; 71C02B372B7BD98F00E93E66 /* NotificationChangeLog.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = NotificationChangeLog.txt; sourceTree = "<group>"; };
EA0B18012A9E236900F2D0CD /* SelectorGroupBase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SelectorGroupBase.swift; sourceTree = "<group>"; }; EA0B18012A9E236900F2D0CD /* SelectorGroupBase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SelectorGroupBase.swift; sourceTree = "<group>"; };
EA0B18032A9E2D2D00F2D0CD /* SelectorBase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SelectorBase.swift; sourceTree = "<group>"; }; EA0B18032A9E2D2D00F2D0CD /* SelectorBase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SelectorBase.swift; sourceTree = "<group>"; };
@ -556,6 +560,7 @@
EA3361B7288B2AAA0071C351 /* ViewProtocol.swift */, EA3361B7288B2AAA0071C351 /* ViewProtocol.swift */,
EAB1D2CC28ABE76000DAE764 /* Withable.swift */, EAB1D2CC28ABE76000DAE764 /* Withable.swift */,
5F21D7BE28DCEB3D003E7CD6 /* Useable.swift */, 5F21D7BE28DCEB3D003E7CD6 /* Useable.swift */,
71BFA7092B7F70E6000DCE33 /* Dropshadowable.swift */,
); );
path = Protocols; path = Protocols;
sourceTree = "<group>"; sourceTree = "<group>";
@ -644,6 +649,7 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
EA5E304B294CBDD00082B959 /* TileContainer.swift */, EA5E304B294CBDD00082B959 /* TileContainer.swift */,
7115BD3B2B84C0C200E0A610 /* TileContainerChangeLog.txt */,
); );
path = TileContainer; path = TileContainer;
sourceTree = "<group>"; sourceTree = "<group>";
@ -936,6 +942,7 @@
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
EAEEECA42B1F934600531FC2 /* IconChangeLog.txt in Resources */, EAEEECA42B1F934600531FC2 /* IconChangeLog.txt in Resources */,
7115BD3C2B84C0C200E0A610 /* TileContainerChangeLog.txt in Resources */,
EA3362042891E14D0071C351 /* VerizonNHGeTX-Bold.otf in Resources */, EA3362042891E14D0071C351 /* VerizonNHGeTX-Bold.otf in Resources */,
71C02B382B7BD98F00E93E66 /* NotificationChangeLog.txt in Resources */, 71C02B382B7BD98F00E93E66 /* NotificationChangeLog.txt in Resources */,
EAEEECA72B1F952000531FC2 /* TabsChangeLog.txt in Resources */, EAEEECA72B1F952000531FC2 /* TabsChangeLog.txt in Resources */,
@ -992,6 +999,7 @@
EAB2376229E9880400AABE9A /* TrailingTooltipLabel.swift in Sources */, EAB2376229E9880400AABE9A /* TrailingTooltipLabel.swift in Sources */,
EAB2376A29E9E59100AABE9A /* TooltipLaunchable.swift in Sources */, EAB2376A29E9E59100AABE9A /* TooltipLaunchable.swift in Sources */,
EAB2375D29E8789100AABE9A /* Tooltip.swift in Sources */, EAB2375D29E8789100AABE9A /* Tooltip.swift in Sources */,
71BFA70A2B7F70E6000DCE33 /* Dropshadowable.swift in Sources */,
EA0D1C452A6AD73000E5C127 /* RawRepresentable.swift in Sources */, EA0D1C452A6AD73000E5C127 /* RawRepresentable.swift in Sources */,
EA985C23296E033A00F2FF2E /* TextArea.swift in Sources */, EA985C23296E033A00F2FF2E /* TextArea.swift in Sources */,
EAF7F0B3289B1ADC00B287F5 /* ActionLabelAttribute.swift in Sources */, EAF7F0B3289B1ADC00B287F5 /* ActionLabelAttribute.swift in Sources */,

View File

@ -454,9 +454,9 @@ open class ButtonIcon: Control, Changeable, FormFieldable {
} }
if let dropshadowable = currentConfig as? Dropshadowable { if let dropshadowable = currentConfig as? Dropshadowable {
addDropShadow(config: dropshadowable) addDropShadow(dropshadowable)
} else { } else {
removeDropShadow() removeDropShadows()
} }
badgeIndicatorCenterXConstraint?.constant = badgeIndicatorOffset.x + badgeIndicatorDefaultSize.width/2 badgeIndicatorCenterXConstraint?.constant = badgeIndicatorOffset.x + badgeIndicatorDefaultSize.width/2
@ -530,37 +530,11 @@ extension ButtonIcon: AppleGuidelinesTouchable {
} }
} }
extension UIView {
fileprivate func addDropShadow(config: Dropshadowable) {
layer.masksToBounds = false
layer.shadowColor = config.shadowColorConfiguration.getColor(self).cgColor
layer.shadowOpacity = Float(config.shadowOpacity)
layer.shadowOffset = config.shadowOffset
layer.shadowRadius = config.shadowRadius
layer.shouldRasterize = true
layer.rasterizationScale = UIScreen.main.scale
layer.shadowPath = UIBezierPath(roundedRect: bounds, cornerRadius: layer.cornerRadius).cgPath
}
fileprivate func removeDropShadow() {
layer.shadowOpacity = 0
layer.shadowRadius = 0
layer.shadowPath = nil
}
}
private protocol Borderable { private protocol Borderable {
var borderWidth: CGFloat { get set } var borderWidth: CGFloat { get set }
var borderColorConfiguration: AnyColorable { get set } var borderColorConfiguration: AnyColorable { get set }
} }
private protocol Dropshadowable {
var shadowColorConfiguration: AnyColorable { get set }
var shadowOpacity: CGFloat { get set }
var shadowOffset: CGSize { get set }
var shadowRadius: CGFloat { get set }
}
private protocol Configuration { private protocol Configuration {
var kind: ButtonIcon.Kind { get set } var kind: ButtonIcon.Kind { get set }
var surfaceType: ButtonIcon.SurfaceType { get set } var surfaceType: ButtonIcon.SurfaceType { get set }

View File

@ -32,20 +32,36 @@ open class TileContainer: Control {
// MARK: - Enums // MARK: - Enums
//-------------------------------------------------- //--------------------------------------------------
/// Enum used to describe the background color choices used for this component. /// Enum used to describe the background color choices used for this component.
public enum BackgroundColor: String, CaseIterable { public enum BackgroundColor: Equatable {
case primary
case secondary
case white case white
case black case black
case gray case custom(String)
case transparent
private var reflectedValue: String { String(reflecting: self) }
public static func == (lhs: Self, rhs: Self) -> Bool {
lhs.reflectedValue == rhs.reflectedValue
}
}
/// Enum used to describe the background effect choices used for this component.
public enum BackgroundEffect {
case transparency
case gradient(String, String)
case none
} }
/// Enum used to describe the padding choices used for this component. /// Enum used to describe the padding choices used for this component.
public enum Padding: String, CaseIterable { public enum Padding {
case padding2X case padding2X
case padding4X case padding4X
case padding6X case padding6X
case padding8X case padding8X
case padding12X case padding12X
case custom(CGFloat)
public var value: CGFloat { public var value: CGFloat {
switch self { switch self {
@ -59,6 +75,8 @@ open class TileContainer: Control {
return VDSLayout.Spacing.space8X.value return VDSLayout.Spacing.space8X.value
case .padding12X: case .padding12X:
return VDSLayout.Spacing.space12X.value return VDSLayout.Spacing.space12X.value
case .custom(let padding):
return padding
} }
} }
} }
@ -106,7 +124,10 @@ open class TileContainer: Control {
open var aspectRatio: AspectRatio = .ratio1x1 { didSet { setNeedsUpdate() } } open var aspectRatio: AspectRatio = .ratio1x1 { didSet { setNeedsUpdate() } }
/// Sets the background color for the component. /// Sets the background color for the component.
open var color: BackgroundColor = .white { didSet { setNeedsUpdate() } } open var color: BackgroundColor = .secondary { didSet { setNeedsUpdate() } }
/// Sets the background effect for the component.
open var backgroundEffect: BackgroundEffect = .none { didSet { setNeedsUpdate() } }
/// Sets the inside padding for the component /// Sets the inside padding for the component
open var padding: Padding = .padding4X { didSet { setNeedsUpdate() } } open var padding: Padding = .padding4X { didSet { setNeedsUpdate() } }
@ -165,6 +186,7 @@ open class TileContainer: Control {
private let cornerRadius = VDSFormControls.borderradius * 2 private let cornerRadius = VDSFormControls.borderradius * 2
private var backgroundColorConfiguration = BackgroundColorConfiguration() private var backgroundColorConfiguration = BackgroundColorConfiguration()
private var dropshadowConfiguration = DropshadowConfiguration()
private var borderColorConfiguration = SurfaceColorConfiguration().with { private var borderColorConfiguration = SurfaceColorConfiguration().with {
$0.lightColor = VDSColor.elementsLowcontrastOnlight $0.lightColor = VDSColor.elementsLowcontrastOnlight
@ -201,24 +223,20 @@ open class TileContainer: Control {
addSubview(highlightView) addSubview(highlightView)
widthConstraint = layoutGuide.widthAnchor.constraint(equalToConstant: 0) widthConstraint = layoutGuide.widthAnchor.constraint(equalToConstant: 0)
widthConstraint?.priority = .defaultHigh
heightGreaterThanConstraint = layoutGuide.heightAnchor.constraint(greaterThanOrEqualToConstant: 44.0) heightGreaterThanConstraint = layoutGuide.heightAnchor.constraint(greaterThanOrEqualToConstant: 44.0)
heightGreaterThanConstraint?.isActive = false heightGreaterThanConstraint?.isActive = false
heightConstraint = layoutGuide.heightAnchor.constraint(equalToConstant: 0) heightConstraint = layoutGuide.heightAnchor.constraint(equalToConstant: 0)
heightConstraint?.priority = .defaultHigh
backgroundImageView.pin(layoutGuide) backgroundImageView.pin(layoutGuide)
backgroundImageView.isUserInteractionEnabled = false backgroundImageView.isUserInteractionEnabled = false
backgroundImageView.isHidden = true backgroundImageView.isHidden = true
containerView.backgroundColor = .clear
containerTopConstraint = containerView.pinTop(anchor: layoutGuide.topAnchor, constant: padding.value) containerTopConstraint = containerView.pinTop(anchor: layoutGuide.topAnchor, constant: padding.value)
containerBottomConstraint = containerView.pinBottom(anchor: layoutGuide.bottomAnchor, constant: padding.value) containerBottomConstraint = layoutGuide.pinBottom(anchor: containerView.bottomAnchor, constant: padding.value)
containerLeadingConstraint = containerView.pinLeading(anchor: layoutGuide.leadingAnchor, constant: padding.value) containerLeadingConstraint = containerView.pinLeading(anchor: layoutGuide.leadingAnchor, constant: padding.value)
containerTrailingConstraint = containerView.pinTrailing(anchor: layoutGuide.trailingAnchor, constant: padding.value) containerTrailingConstraint = layoutGuide.pinTrailing(anchor: containerView.trailingAnchor, constant: padding.value)
highlightView.pin(layoutGuide) highlightView.pin(layoutGuide)
highlightView.isHidden = true highlightView.isHidden = true
@ -228,7 +246,6 @@ open class TileContainer: Control {
layer.cornerRadius = cornerRadius layer.cornerRadius = cornerRadius
backgroundImageView.layer.cornerRadius = cornerRadius backgroundImageView.layer.cornerRadius = cornerRadius
highlightView.layer.cornerRadius = cornerRadius highlightView.layer.cornerRadius = cornerRadius
} }
/// Resets to default settings. /// Resets to default settings.
@ -268,8 +285,8 @@ open class TileContainer: Control {
containerTopConstraint?.constant = padding.value containerTopConstraint?.constant = padding.value
containerLeadingConstraint?.constant = padding.value containerLeadingConstraint?.constant = padding.value
containerBottomConstraint?.constant = -padding.value containerBottomConstraint?.constant = padding.value
containerTrailingConstraint?.constant = -padding.value containerTrailingConstraint?.constant = padding.value
if let width, aspectRatio == .none && height == nil{ if let width, aspectRatio == .none && height == nil{
widthConstraint?.constant = width widthConstraint?.constant = width
@ -293,6 +310,12 @@ open class TileContainer: Control {
widthConstraint?.isActive = false widthConstraint?.isActive = false
heightConstraint?.isActive = false heightConstraint?.isActive = false
} }
if showDropShadows, surface == .light {
addDropShadow(dropshadowConfiguration)
} else {
removeDropShadows()
}
applyBackgroundEffects()
} }
//-------------------------------------------------- //--------------------------------------------------
@ -310,6 +333,36 @@ open class TileContainer: Control {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Private Methods // MARK: - Private Methods
//-------------------------------------------------- //--------------------------------------------------
private func applyBackgroundEffects() {
let color = backgroundColorConfiguration.getColor(self)
var alphaConfiguration: CGFloat = 1.0
let imageFallbackColor = imageFallbackColorConfiguration.getColor(self)
switch backgroundEffect {
case .transparency:
alphaConfiguration = 0.8
removeGradientLayer()
case .gradient(let firstColor, let secondColor):
alphaConfiguration = 1.0
addGradientLayer(with: UIColor(hexString: firstColor), secondColor: UIColor(hexString: secondColor))
backgroundImageView.isHidden = true
backgroundImageView.alpha = 1.0
case .none:
alphaConfiguration = 1.0
removeGradientLayer()
}
if let backgroundImage {
backgroundImageView.image = backgroundImage
backgroundImageView.isHidden = false
backgroundImageView.alpha = alphaConfiguration
backgroundColor = imageFallbackColor.withAlphaComponent(alphaConfiguration)
} else {
backgroundImageView.isHidden = true
backgroundImageView.alpha = 1.0
backgroundColor = color.withAlphaComponent(alphaConfiguration)
}
}
private func ratioSize(for width: CGFloat) -> CGSize { private func ratioSize(for width: CGFloat) -> CGSize {
var height: CGFloat = width var height: CGFloat = width
@ -343,22 +396,40 @@ open class TileContainer: Control {
} }
extension TileContainer { extension TileContainer {
class BackgroundColorConfiguration: ObjectColorable {
struct DropshadowConfiguration: Dropshadowable {
var shadowColorConfiguration: AnyColorable = SurfaceColorConfiguration().with {
$0.lightColor = VDSColor.elementsPrimaryOnlight
}.eraseToAnyColorable()
var shadowOpacity: CGFloat = 0.01
var shadowOffset: CGSize = .init(width: 0, height: 6)
var shadowRadius: CGFloat = 3
}
final class BackgroundColorConfiguration: ObjectColorable {
typealias ObjectType = TileContainer typealias ObjectType = TileContainer
let primaryColorConfig = SurfaceColorConfiguration(VDSColor.backgroundPrimaryLight, VDSColor.backgroundPrimaryDark)
let secondaryColorConfig = SurfaceColorConfiguration(VDSColor.backgroundSecondaryLight, VDSColor.backgroundSecondaryDark)
let grayColorConfig = SurfaceColorConfiguration(VDSColor.backgroundSecondaryLight, VDSColor.backgroundSecondaryDark)
let whiteColorConfig = SurfaceColorConfiguration(VDSColor.paletteWhite, VDSColor.paletteWhite)
let blackColorConfig = SurfaceColorConfiguration(VDSColor.paletteBlack, VDSColor.paletteBlack)
required init() { } required init() { }
func getColor(_ object: TileContainer) -> UIColor { func getColor(_ object: TileContainer) -> UIColor {
switch object.color { switch object.color {
case .primary:
primaryColorConfig.getColor(object.surface)
case .secondary:
secondaryColorConfig.getColor(object.surface)
case .white: case .white:
return VDSColor.backgroundPrimaryLight whiteColorConfig.getColor(object.surface)
case .black: case .black:
return VDSColor.backgroundPrimaryDark blackColorConfig.getColor(object.surface)
case .gray: case .custom(let hexCode):
return VDSColor.backgroundSecondaryLight UIColor(hexString: hexCode)
case .transparent:
return UIColor.clear
} }
} }
} }

View File

@ -0,0 +1,90 @@
MM/DD/YYYY
----------------
02/01/2022
----------------
- ACTION | Migrated Spec file from working file into VDS Brand 3.0 Core SPECs & Test App.
02/02/2022
----------------
- Elements | Added option for user to manually define a custom Padding valueElements.
- Elements | Removed option for 40px Padding
- Elements | Added background options of Hex code and Transparency.
02/07/2022
----------------
- Anatomy | Updated descriptions to simplify. (Removed “Tile” from many)
02/08/2022
----------------
- Elements | Background color section updated
- Elements | Removed option for 20px Padding value
- Configurations | Surface section added
- Configurations | Multiple sections updated
- Behaviors | Interaction section added
- States | Multiple sections updated/moved
- ACTION | Sent to Accessibility Team to review
02/14/2022
----------------
- ACTION | Received sign off from Accessibility
- ACTION | Sent to Talia for design review
02/21/2022
----------------
- Elements | Background colors and tokens updated.
- ACTION | Ready for dev review.
02/22/2022
----------------
- Elements | Background names updated to infer surface prop selection.
- ACTION | Web dev handoff completed.
12/15/2022
----------------
- States | Android drop shadow specs added, along with screenshot to the right of specs.
- States | Added "(web only)" to any instance of "keyboard focus".
- States | Replaced focus border pixel and style & spacing values with tokens.
- Elements | Updated border color values to use element tokens.
- Configurations | Updated border and drop shadow section titles to “Show border” and “Show drop shadow.”
01/18/2023
----------------
- Anatomy | Updated item #2 to “Padding” from “Container Internal Padding”
05/11/2023
----------------
- Removed showdropshadow prop from Configurations (dropshadow will be on automatically now for Surface=Light)
- Updated states frame to remove states featuring dropshadow suppression, clarified state names, and removed inaccurate dev notes.
06/15/2023
----------------
- Added showDropShadow prop back into Configurations.
- Moved Padding to Configurations
11/09/2023
----------------
- Updated showBorder section to match API prop names/values.
- Moved Padding to Configurations.
11/20/2023
----------------
- Added corner radius token in the Anatomy
- Updated visuals to reflect new corner radius value - 12px
- Updated focus border corner radius to 14px
- View changes
11/27/2023
----------------
- Updated “border radius” to “corner radius” in Anatomy
- Updated “focus border radius” to “focus corner radius” in States
- View changes
12/14/2023
----------------
- Added backgroundColor configuration section, removed Background Colors element section
- Added secondary, primary backgroundColor options
- Simplified backgroundImage section to remove backgroundColor example
- Added background property section, with examples
- Deprecated the gray backgroundColor option
- View changes

View File

@ -0,0 +1,64 @@
//
// Dropshadowable.swift
// VDS
//
// Created by Bandaru, Krishna Kishore on 16/02/24.
//
import Foundation
import UIKit
protocol Dropshadowable {
var shadowColorConfiguration: AnyColorable { get set }
var shadowOpacity: CGFloat { get set }
var shadowOffset: CGSize { get set }
var shadowRadius: CGFloat { get set }
}
extension ViewProtocol where Self: UIView {
func addDropShadow(_ config: Dropshadowable) {
removeDropShadows()
layer.backgroundColor = backgroundColor?.cgColor
layer.masksToBounds = false
let shadowPath = UIBezierPath(roundedRect: bounds, cornerRadius: layer.cornerRadius)
let shadowLayer = CALayer()
shadowLayer.shadowPath = shadowPath.cgPath
shadowLayer.frame = bounds
shadowLayer.position = center
shadowLayer.backgroundColor = UIColor.clear.cgColor
shadowLayer.cornerRadius = layer.cornerRadius
shadowLayer.shadowColor = config.shadowColorConfiguration.getColor(self).cgColor
shadowLayer.shadowOpacity = Float(config.shadowOpacity)
shadowLayer.shadowOffset = .init(width: config.shadowOffset.width, height: config.shadowOffset.height)
shadowLayer.shadowRadius = config.shadowRadius
shadowLayer.name = "dropShadowLayer"
shadowLayer.shouldRasterize = true
shadowLayer.rasterizationScale = UIScreen.main.scale
layer.insertSublayer(shadowLayer, at: 0)
}
func removeDropShadows() {
layer.sublayers?.removeAll { $0.name == "dropShadowLayer" }
}
func addGradientLayer(with firstColor: UIColor, secondColor: UIColor) {
removeGradientLayer()
let gradientLayer = CAGradientLayer()
gradientLayer.frame = bounds
gradientLayer.startPoint = CGPoint(x: 0, y: 1)
gradientLayer.endPoint = CGPoint(x: 1, y: 0)
gradientLayer.position = center
gradientLayer.shouldRasterize = true
gradientLayer.rasterizationScale = UIScreen.main.scale
gradientLayer.cornerRadius = layer.cornerRadius
gradientLayer.colors = [firstColor.cgColor, secondColor.cgColor]
gradientLayer.name = "gradientLayer"
layer.insertSublayer(gradientLayer, at: 0)
}
func removeGradientLayer() {
layer.sublayers?.removeAll { $0.name == "gradientLayer" }
}
}