Hw.Master
Hw.Master

Reputation: 4452

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!

Upvotes: 28

Views: 33842

Answers (7)

Oz Shabat
Oz Shabat

Reputation: 1622

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
            })
        }
}

Upvotes: 0

Lance Samaria
Lance Samaria

Reputation: 19582

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
}

Upvotes: 4

Fernando Cardenas
Fernando Cardenas

Reputation: 1232

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.

Upvotes: 0

Guillaume Algis
Guillaume Algis

Reputation: 11016

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;

Upvotes: 65

zeeshan
zeeshan

Reputation: 5053

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
    }
}

Upvotes: 7

A'sa Dickens
A'sa Dickens

Reputation: 2085

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

Upvotes: 1

lindon fox
lindon fox

Reputation: 3318

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;

Upvotes: 7

Related Questions