Swift - Apply Shadow to circular button on click - ios

I am creating circular buttons as follow:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let button = GradientButton.createCircularButton(20, yPos: 20, width: 30, height: 30, circleValue:20)
button.addTarget(self, action: #selector(ViewController.didCircleBtnTouched(_:)), forControlEvents: UIControlEvents.TouchUpInside)
self.view.addSubview(button)
}
}
enum ColorType {
case red, green, orange
}
class GradientButton: UIButton {
var colorType: ColorType?
public class func createCircularButton(xPos: CGFloat, yPos: CGFloat, width: CGFloat, height: CGFloat, circleValue: Int) -> GradientButton {
let button = GradientButton()
button.titleLabel!.font = UIFont(name:"HelveticaNeue", size: 12)
let buttonFrame = CGRect(x: xPos, y: yPos, width: width, height: height)
button.frame = buttonFrame
button.backgroundColor = UIColor.clearColor()
button.backgroundColor = UIColor.whiteColor()
button.layer.borderWidth = 1
button.layer.cornerRadius = 15.0
//this helps making it circular not rectangle
button.clipsToBounds = true
let red = UIColor(red:134/255, green:16/255, blue:1/255, alpha:1.0)//red
let green = UIColor(red:0/255, green:136/255, blue:43/255, alpha:1.0)//green
let orange = UIColor(red:243/255, green:144/255, blue:25/255, alpha:1.0)//orange
if(circleValue <= 3){
button.colorType = .green
button.layer.borderColor = UIColor.greenColor().CGColor
button.setTitleColor(green, forState: .Normal)
} else if(circleValue > 3 && circleValue <= 7){
button.colorType = .orange
button.layer.borderColor = UIColor.orangeColor().CGColor
button.setTitleColor(orange, forState: .Normal)
} else if(circleValue > 7){
button.colorType = .red
button.layer.borderColor = UIColor.redColor().CGColor
button.setTitleColor(red, forState: .Normal)
}
button.setTitle("\(circleValue)", forState: .Normal)
return button
}
}
And on click of button I am applying gradient as follow:
func didCircleBtnTouched(sender:GradientButton!){
ApplyGradientToButton(sender)
}
func ApplyGradientToButton(sender: GradientButton!){
var color1 = UIColor()
var color2 = UIColor()
if(sender.colorType == .red){
color1 = UIColor(red:134/255, green:16/255, blue:1/255, alpha:1.0)
color2 = UIColor(red:200/255, green:37/255, blue:6/255, alpha:1.0)
}
else if(sender.colorType == .green) {
color1 = UIColor(red:0/255, green:136/255, blue:43/255, alpha:1.0)
color2 = UIColor(red:112/255, green:191/255, blue:65/255, alpha:1.0)
}
else if(sender.colorType == .orange) {
color1 = UIColor(red:200/255, green:110/255, blue:1/255, alpha:1.0)
color2 = UIColor(red:239/255, green:149/255, blue:26/255, alpha:1.0)
}
sender.setTitleColor(UIColor.whiteColor(), forState: .Normal)
var layer = sender.layer
layer.shadowColor = UIColor.blackColor().CGColor
layer.shadowOffset = CGSize(width: 0.0, height: 5.0)
layer.shadowOpacity = 1.0
layer.shadowRadius = 10.0
sender.applyGradient([color2, color1], locations: [0.0, 0.90])
}
I need to display shadow around circular button on button click. But shadow is not getting displayed.
I think button.clipsToBounds = true is responsible as when I am not using this property shadow appears. Unfortunately by removing this property my circular button becomes rectangular after click which is not desirable.
Is there any way to display the shadow without changing the shape of button?
Please advise?
Current output:
Expected output:

Well you can't clip/mask to bounds and add a shadow, as it will also be clipped or masked too.
The solution is to add the shadow on a separate layer and add the image as a sublayer.
This is described in many posts here:
https://stackoverflow.com/a/25591916/312312
Swift - Problems with corner radius and drop shadow
and many many more

Just Put this code in viewController.swift file.. (Or any other file)
extension UIView {
func setRadiusWithShadow(_ radius: CGFloat? = nil) {
self.layer.cornerRadius = radius ?? self.frame.width / 2
self.layer.shadowColor = UIColor.darkGray.cgColor
self.layer.shadowOffset = CGSize(width: 1.5, height: 1.5)
self.layer.shadowRadius = 1.0
self.layer.shadowOpacity = 0.7
self.layer.masksToBounds = false
}
}
and then apply to your button..
btnEdit.setRadiusWithShadow()
Yeah... Just see the output... Everything is done...
Note: You can change CGSize(width: 1.5, height: 1.5) values as per your desired need...

Related

How to Change uitextfield leftView image tintColor on editing

I'm trying to achieve UITextField editing or not editing style like this:
But the trickiest part for me is How to change that left image tint color. I have achieved this so far:
My code:
UITextField
lazy var email: UITextField = {
let name = UITextField()
name.layer.cornerRadius = 17.5
name.layer.borderColor = UIColor(red: 0.55, green: 0.61, blue: 0.69, alpha: 0.5).cgColor
name.layer.borderWidth = 1.5
name.placeholder = "Email"
name.font = UIFont.systemFont(ofSize: 15)
name.textColor = UIColor(red: 0.55, green: 0.61, blue: 0.69, alpha: 1)
name.backgroundColor = .clear
name.leftViewMode = UITextFieldViewMode.always
name.delegate = self
name.translatesAutoresizingMaskIntoConstraints = false
return name
}()
leftImage func:
func addLeftImageTo(txtField: UITextField, andImage img: UIImage) {
let leftView = UIView(frame: CGRect(x: 0, y: 0, width: 42.75, height: 40))
let centerX: CGFloat = (leftView.frame.midX) - (img.size.width / 2)
let centerY: CGFloat = (leftView.frame.midY) - (img.size.height / 2)
let leftImageView = UIImageView(frame: CGRect(x: centerX + 2 , y: centerY - 1, width: img.size.width, height: img.size.height))
leftImageView.contentMode = .scaleAspectFit
leftImageView.image = img
leftView.addSubview(leftImageView)
txtField.leftView = leftView
txtField.leftViewMode = .always
}
Adding leftImages:
let emailLeftImg = UIImage(named: "ic_txt_field_email")
addLeftImageTo(txtField: email, andImage: emailLeftImg!)
let passwordLeftImg = UIImage(named: "ic_txt_field_password")
addLeftImageTo(txtField: password, andImage: passwordLeftImg!)
editingBegains and Ending:
func textFieldDidBeginEditing(_ textField: UITextField) {
self.setTextBorder(textField: textField, color: UIColor.white, borderColor: UIColor.white, isSelected: true)
}
func textFieldDidEndEditing(_ textField: UITextField) {
self.setTextBorder(textField: textField, color: UIColor.clear, borderColor: UIColor(red: 0.55, green: 0.61, blue: 0.69, alpha: 0.5), isSelected: false)
}
func setTextBorder(textField: UITextField, color: UIColor, borderColor: UIColor, isSelected: Bool) {
textField.backgroundColor = color
textField.layer.borderColor = borderColor.cgColor
textField.tintColor = UIColor(red: 1.0, green: 0.2, blue: 0.33, alpha: 1)
textField.layer.masksToBounds = false
if isSelected == true {
textField.layer.shadowRadius = 3.0
textField.layer.shadowColor = UIColor.black.cgColor
textField.layer.shadowOffset = CGSize(width: 0, height: 2)
textField.layer.shadowOpacity = 0.125
} else {
textField.layer.shadowRadius = 0
textField.layer.shadowColor = UIColor.clear.cgColor
textField.layer.shadowOffset = CGSize(width: 0, height: 0)
textField.layer.shadowOpacity = 0
}
}
I had tried adding this code to change Image color but it didn't work.
var picTintColor: Bool = false
In LeftImage func:
if picTintColor == true {
leftImageView.image = img.withRenderingMode(.alwaysTemplate)
leftImageView.tintColor = .blue
} else {
leftImageView.image = img
}
And in editingBegains and Ending func:
if isSelected == true {
picTintColor = true
} else {
picTintColor = false
}
I'm a complete noob in IOS programming so thanks for your patience and sorry for my bad english. Thanks!
According the code ,it actually can not pass isSelected signal to the leftImageView,maybe leftImageView get in laster is not the earlier ,or the signal not pass successly.
I suggest that a easy way to do, just in editingBegains and Ending: to do what you want change the imageview,like this:
func textFieldDidBeginEditing(_ textField: UITextField) {
let emailLeftImg = UIImage(named: "ic_txt_field_email")
addLeftImageTo(txtField: email, andImage: emailLeftImg!)
}
func addLeftImageTo(txtField: UITextField, andImage img: UIImage) {
let leftView = UIView(frame: CGRect(x: 0, y: 0, width: 42.75, height: 40))
let centerX: CGFloat = (leftView.frame.midX) - (img.size.width / 2)
let centerY: CGFloat = (leftView.frame.midY) - (img.size.height / 2)
let leftImageView = UIImageView(frame: CGRect(x: centerX + 2 , y: centerY - 1, width: img.size.width, height: img.size.height))
leftImageView.contentMode = .scaleAspectFit
if picTintColor == true {
leftImageView.image = img.withRenderingMode(.alwaysTemplate)
leftImageView.tintColor = .blue
} else {
leftImageView.image = img
}
leftView.addSubview(leftImageView)
txtField.leftView = leftView
txtField.leftViewMode = .always
}
and in end delgate method ,just do that ,you can try this way to test.Hope to help you.

Remove title shadow from shadowed button

I'm trying to remove shadow from my button title.
How I make shadow and corner radius:
func makeShadowRounded() {
layer.cornerRadius = 25
layer.shadowColor = UIColor.darkGray.cgColor
layer.shadowOffset = CGSize(width: 0, height: 2)
layer.shadowRadius = 3
layer.shadowOpacity = 0.15
}
My button with white background:
let signInButton: UIButton = {
let button = UIButton()
button.layer.borderColor = UIColor.customBlue.cgColor
button.layer.borderWidth = 0.5
button.setTitle("Sign In", for: .normal)
button.setTitleColor(.customBlue, for: .normal)
button.makeShadowRounded()
return button
}()
For removing/replacing (by different color) shadow i replaced setTitle and setTitleColor by:
let shadow = NSShadow()
shadow.shadowColor = UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
shadow.shadowOffset = CGSize(width: 0, height: 2)
shadow.shadowBlurRadius = 2
let attributedString = NSAttributedString(string: "Sign In", attributes: [
NSAttributedStringKey.shadow : shadow,
NSAttributedStringKey.foregroundColor : UIColor.customBlue
])
button.setAttributedTitle(attributedString, for: .normal)
However, It isn't working properly. What will be the better solution for that issue?

TicTacToe how to reset containerView content?

I need some help over here. I try to learn... some things and practice but i'm not able to manage that function.
I have this function creating the container view:
func createGameView() {
let containerView = UIView()
containerView.frame = CGRect(x: 0,
y: self.screenHeight * 0.4,
width: screenWidth,
height: screenHeight * 0.6)
containerView.backgroundColor = UIColor(red:0.99, green:0.13, blue:0.00, alpha:1)
self.view.addSubview(containerView)
After that I have a function who will populate the container view with 9 squares
func createGridView( _ container : UIView) {
let buttonWidth = container.frame.size.width / 3
let buttonHeight = container.frame.size.height / 3
for i in [0,1,2] {
for j in 0...2 {
let button = UIButton(frame:
CGRect( x : buttonWidth * CGFloat (i),
y :buttonHeight * CGFloat (j),
width : buttonWidth,
height : buttonHeight ))
button.backgroundColor = UIColor.init(colorLiteralRed: 0.1, green: 0.89, blue: 0.05, alpha: 1)
button.layer.borderColor = UIColor.black.cgColor
button.layer.borderWidth = 1.0
container.addSubview(button)
button.addTarget(self, action: #selector(GameViewController.addGameValue(sender:)), for: .touchUpInside)
button.tag = i + 3 * j
self.gameButtons.append(button)
}
}
}
And I have a button called RESET
var resetButton = UIButton(frame:
CGRect(x: Double(containerView.frame.size.width - 100),
y: Double(containerView.frame.size.height - 60),
width: 60,
height: 40.0)
)
resetButton.setTitle ("Reset", for: UIControlState.normal)
resetButton.setTitleColor(UIColor.black, for: UIControlState.normal)
resetButton.setTitleColor(UIColor.white, for: .highlighted)
resetButton.layer.borderWidth = 1.0
resetButton.layer.borderColor = UIColor.black.cgColor
resetButton.layer.cornerRadius = 5.0
resetButton.addTarget(self, action: #selector(GameViewController.resetGame), for: UIControlEvents.touchUpInside)
containerView.addSubview(resetButton)
This is where i got a problem :(
func resetGame (sender: UIButton) {
// .addTarget(self, action: #selector(self.createGameView), for: .touchUpInside)
print(" reset me ")
// .addTarget(self, action: #selector(GameViewController.resetGame), for: .touchUpInside)
}
Anyone can tell me why none of those are not working to reset the value ? Is a tic tac toe game, and after put some x and 0 i want to restore the gridView to intial state. Got no ideea how to do it.
you already have all of the buttons that you need added to the view after createGridView is called, so on reset all you have to do is reset the button state, clear any scores/points and your ready to start again.
func resetGame() {
// reset any scores, colors etc
for button in self.gameButtons {
button.setTitle ("", for: UIControlState.normal)
button.backgroundColor = UIColor.init(colorLiteralRed: 0.1, green: 0.89, blue: 0.05, alpha: 1)
}
}

Circular Gradient Buttons in Swift

I am creating circular button in the following way:
func CreateCirclularButton(xpos:CGFloat, ypos:CGFloat, Circlevalue:CGFloat, ParentView:UIView, TagValue:Int){
let button = UIButton()
var buttonFrame = EventStripe.frame
buttonFrame.origin.x = xpos
buttonFrame.origin.y = ypos
buttonFrame.size.width = 30
buttonFrame.size.height = 30
button.frame = buttonFrame
button.tag = TagValue
button.backgroundColor = UIColor.clearColor()
button.backgroundColor = UIColor.whiteColor()
button.layer.borderWidth=1
button.layer.cornerRadius=15.0
if(Circlevalue<=4){
button.layer.borderColor = UIColor(red:0/255, green:136/255, blue:43/255, alpha:1.0).CGColor
button.setTitleColor(UIColor(red:0/255, green:136/255, blue:43/255, alpha:1.0), forState: UIControlState.Normal)
}else if(Circlevalue>4 && Circlevalue<=7){
button.layer.borderColor = UIColor(red:243/255, green:144/255, blue:25/255, alpha:1.0).CGColor
button.setTitleColor(UIColor(red:244/255, green:179/255, blue:100/255, alpha:1.0), forState: UIControlState.Normal)
}else{
button.layer.borderColor = UIColor(red:200/255, green:37/255, blue:6/255, alpha:1.0).CGColor
button.setTitleColor(UIColor(red:200/255, green:37/255, blue:6/255, alpha:1.0), forState: UIControlState.Normal)
}
let circleval = Int(Circlevalue)
button.setTitle("\(circleval)", forState: UIControlState.Normal)
button.addTarget(self, action: #selector(ViewController.didCircleBtnTouched), forControlEvents: UIControlEvents.TouchUpInside)
ParentView.addSubview(button)
}
When button is clicked, I am applying gradient to the clicked button in following way:
func didCircleBtnTouched(sender:UIButton!){
//let color = UIColor(red:134/255, green:16/255, blue:1/255, alpha:1.0)//red
//let color = UIColor(red:0/255, green:136/255, blue:43/255, alpha:1.0)//green
//let color = UIColor(red:243/255, green:144/255, blue:25/255, alpha:1.0)//orange
//For setting Gradient to selected circle -- unable to identify the border color from selected button
//if any how we can identify the border color
let color1 = UIColor()
let color2 = UIColor()
if(bordercolor == red){
color1 = UIColor(red:200/255, green:37/255, blue:6/255, alpha:1.0)
color2 = UIColor(red:134/255, green:16/255, blue:1/255, alpha:1.0)
}
else if(bordercolor == Orange){
color1 = UIColor(red:243/255, green:144/255, blue:25/255, alpha:1.0)
color2 = UIColor(red:200/255, green:110/255, blue:1/255, alpha:1.0)
}
else if(bordercolor == red){
color1 = UIColor(red:37/255, green:200/255, blue:6/255, alpha:1.0)
color2 = UIColor(red:16/255, green:134/255, blue:1/255, alpha:1.0)
}
sender.applyGradient([color1, color2 ], locations: [0.0, 0.90])
}
This is the extension I used for applying gradient:
extension UIView {
func applyGradient(colours: [UIColor]) -> Void {
self.applyGradient(colours, locations: nil)
}
func applyGradient(colours: [UIColor], locations: [NSNumber]?) -> Void
{
let gradient: CAGradientLayer = CAGradientLayer()
gradient.frame = self.bounds
gradient.cornerRadius=3.0
gradient.colors = colours.map { $0.CGColor }
gradient.locations = locations
self.layer.insertSublayer(gradient, atIndex: 0)
}
}
In doing so I have two issues:
Not able to identify the color of selected button so I can apply respective gradient to that button.
When I apply gradient to button, the button becomes rectangular instead of circular.
Ideally needed:
This is how it looks now:
How can I resolve this?
For the first case you can do
button.layer.cornerRadius=15.0
//this line is what you need
button.clipsToBounds = true
For second case you can subclass the UIButton and create an ivar colorType of enum.
Then based on enum you can check what is the color of your button.
Below is the example of the code of a ViewController
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let button = GradientButton.createCircularButton(xPos: 100, yPos: 100, width: 30, height: 30, circleValue: 7)
button.addTarget(self, action: #selector(didCircleBtnTouched(sender:)), for: .touchUpInside)
self.view.addSubview(button)
}
func didCircleBtnTouched(sender: GradientButton!){
var color1 = UIColor()
var color2 = UIColor()
if(sender.colorType == .red){
color1 = UIColor(red:200/255, green:37/255, blue:6/255, alpha:1.0)
color2 = UIColor(red:134/255, green:16/255, blue:1/255, alpha:1.0)
}
else if(sender.colorType == .green) {
color1 = UIColor(red:37/255, green:200/255, blue:6/255, alpha:1.0)
color2 = UIColor(red:16/255, green:134/255, blue:1/255, alpha:1.0)
}
else if(sender.colorType == .orange) {
color1 = UIColor(red:243/255, green:144/255, blue:25/255, alpha:1.0)
color2 = UIColor(red:200/255, green:110/255, blue:1/255, alpha:1.0)
}
sender.setTitleColor(UIColor.white, for: .normal)
sender.applyGradient(colours: [color1, color2 ], locations: [0.0, 0.90])
}
}
enum ColorType {
case red, green, orange
}
class GradientButton: UIButton {
var colorType: ColorType?
public class func createCircularButton(xPos: CGFloat, yPos: CGFloat, width: CGFloat, height: CGFloat, circleValue: Int) -> GradientButton {
let button = GradientButton()
let buttonFrame = CGRect(x: xPos, y: yPos, width: width, height: height)
button.frame = buttonFrame
button.backgroundColor = UIColor.clear
button.backgroundColor = UIColor.white
button.layer.borderWidth = 1
button.layer.cornerRadius = 15.0
//this helps making it circular not rectangle
button.clipsToBounds = true
let red = UIColor(red:134/255, green:16/255, blue:1/255, alpha:1.0)//red
let green = UIColor(red:0/255, green:136/255, blue:43/255, alpha:1.0)//green
let orange = UIColor(red:243/255, green:144/255, blue:25/255, alpha:1.0)//orange
if(circleValue <= 4){
button.colorType = .red
button.layer.borderColor = red.cgColor
button.setTitleColor(red, for: .normal)
} else if(circleValue > 4 && circleValue <= 7){
button.colorType = .green
button.layer.borderColor = green.cgColor
button.setTitleColor(green, for: .normal)
} else {
button.colorType = .orange
button.layer.borderColor = orange.cgColor
button.setTitleColor(orange, for: .normal)
}
button.setTitle("\(circleValue)", for: .normal)
return button
}
//keep gradient buttons here
func applyGradient(colours: [UIColor]) -> Void {
self.applyGradient(colours: colours, locations: nil)
}
func applyGradient(colours: [UIColor], locations: [NSNumber]?) -> Void
{
let gradient: CAGradientLayer = CAGradientLayer()
gradient.frame = self.bounds
gradient.cornerRadius=3.0
gradient.colors = colours.map { $0.cgColor }
gradient.locations = locations
self.layer.insertSublayer(gradient, at: 0)
}
}
Try using this:
button.layer.cornerRadius = button.frame.size.width/2.0
button.layer.borderColor = UIColor(red:200/255, green:37/255, blue:6/255, alpha:1.0).CGColor
button.backgroundColor = UIColor.whiteColor()
button.tintColor = UIColor(red:200/255, green:37/255, blue:6/255, alpha:1.0).CGColor
button.layer.masksToBounds = true
Make sure your button must have same Height and Width and there is image required for Button.

iOS add / remove shadow from a view

I do not understand how to remove a shadow that was added to a view.
I add to my view in initWithFrame a shadow in this way:
self.layer.borderWidth = 2;
self.layer.borderColor = [UIColor clearColor].CGColor;
self.backgroundColor = [UIColor greenColor];
[self.layer setCornerRadius:8.0f];
CALayer *layer = self.layer;
layer.shadowOffset = CGSizeMake(2, 2);
layer.shadowColor = [[UIColor blackColor] CGColor];
layer.cornerRadius = 8.0f;
layer.shadowRadius = 3.0f;
layer.shadowOpacity = 0.80f;
layer.shadowPath = [[UIBezierPath bezierPathWithRect:layer.bounds] CGPath];
After in the execution of the app I want to remove the shadow from this view. I've tried using:
layer.hidden = YES;
or
self.layer.hidden = YES;
but this hides the view completely, not just the added shadow.
Is there a way to retrieve the added shadow from a view and then hide it?
Thanks!
I guess you could use the shadowOpacity property of your CALayer.
So this should work:
self.layer.shadowOpacity = 0;
See the CALayer's shadowOpacity documentation page
And to show your shadow use:
self.layer.shadowOpacity = 1.0;
Sorry, not sure the correct way, but have you tried changing the properties of the layer shadow? For example, one of these;
layer.shadowOffset = CGSizeMake(0, 0);
layer.shadowColor = [[UIColor clearColor] CGColor];
layer.cornerRadius = 0.0f;
layer.shadowRadius = 0.0f;
layer.shadowOpacity = 0.00f;
Swift 4.2
I am using this in my code for labels and navigation bar.
extension UIView {
func shadow(_ height: Int = 5) {
self.layer.masksToBounds = false
self.layer.shadowRadius = 4
self.layer.shadowOpacity = 1
self.layer.shadowColor = UIColor.gray.cgColor
self.layer.shadowOffset = CGSize(width: 0 , height: height)
}
func removeShadow() {
self.layer.shadowOffset = CGSize(width: 0 , height: 0)
self.layer.shadowColor = UIColor.clear.cgColor
self.layer.cornerRadius = 0.0
self.layer.shadowRadius = 0.0
self.layer.shadowOpacity = 0.0
}
}
I tried the other answers, the only thing that worked for me was to toggle layer.masksToBounds to true/false
lazy var myView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = .white
view.layer.cornerRadius = 5
view.layer.shadowColor = UIColor.black.cgColor
view.layer.shadowOpacity = 3
view.layer.shadowOffset = .zero
view.layer.shadowRadius = 5
return view
}()
func showShadow() {
myView.layer.masksToBounds = false
}
func hideShadow() {
myView.layer.masksToBounds = true
}
the "layer" that you are trying to make hidden is the layer of the object that you are having a shadow to it's not a visible aspect.. only the objects with in the layer... it's rather confusing to conceptualize anyways, the only way to remove the shadow is to undo what you originally did, which was suggested above, there is no defined property that you can just toggle a bool and make the shadow go away
Swift 5.+
My solution was to add a shadowBackgroundView, which has a removable shadowLayer. In this way I could easyly remove the layer without resetting the shadow properties.
class ViewController: UIViewController {
private let shadowBackgroundView: UIView = {
let view = UIView(frame: CGRect(x: 100, y: 100, width: 100, height: 100))
view.layer.masksToBounds = false
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
view.addSubview(shadowBackgroundView)
// the view you want to add the shadow
let dummyView = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
dummyView.backgroundColor = .red
shadowBackgroundView.addSubview(dummyView)
let addShadowButton = UIButton(frame: CGRect(x: 100, y: 300, width: 140, height: 50))
addShadowButton.backgroundColor = .blue
addShadowButton.setTitle("Add Shadow", for: .normal)
addShadowButton.addTarget(self, action: #selector(addShadow), for: .touchUpInside)
let removeShadowButton = UIButton(frame: CGRect(x: 100, y: 450, width: 140, height: 50))
removeShadowButton.backgroundColor = .blue
removeShadowButton.setTitle("Remove Shadow", for: .normal)
removeShadowButton.addTarget(self, action: #selector(removeShadow), for: .touchUpInside)
view.addSubview(addShadowButton)
view.addSubview(removeShadowButton)
}
#objc
func addShadow() {
let shadowLayer = CALayer()
shadowLayer.name = "ShadowLayer"
shadowLayer.shadowColor = UIColor.black.cgColor
shadowLayer.shadowOpacity = 1
shadowLayer.shadowOffset = .zero
shadowLayer.shadowRadius = 10
shadowLayer.shadowPath = UIBezierPath(rect: shadowBackgroundView.bounds).cgPath
// Otherwise the shadow will appear above the dummyView
shadowLayer.zPosition = -1
shadowBackgroundView.layer.addSublayer(shadowLayer)
}
#objc
func removeShadow() {
// Alternatively, you could also create the shadowLayer as a property, so you could call shadowLayer.removeFromSuperLayer()
shadowBackgroundView.layer.sublayers?.first { $0.name == "ShadowLayer" }?.removeFromSuperlayer()
}
}
As a Note, for the UITableViewCell, you wouldnt need to add a shadowBackgroundView, but you could add the shadowLayer directly to cell.view.layer, which serves as the backgroundView for the cell.contentView.
Swift 4.2
Just to add to the other answers, you could change the opacity through animation:
#IBAction func btnDidTap(_ sender: UICustomGestureRecognizer) {
guard let view = sender.view else {return}
if sender.state == .began {
UIView.animate(withDuration: 0.3,
animations: {
view.layer.shadowOpacity = 0
})
} else if sender.state == .ended {
UIView.animate(withDuration: 0.3,
animations: {
view.layer.shadowOpacity = 1
})
}
}

Resources