Search code examples
iosswiftuibuttoncalayeruibezierpath

How to mask a UIButton in Swift?


I have a complicated Stack view that has many arranged labels and buttons. When I have attempted to mask the whole stack view in order to enforce a corner radius, the buttons within the stack view no longer worked (action selectors not triggered upon touch inside). I have decided to simplify the problem first to one button and one mask like so:

    let mask = UIView()
    mask.translatesAutoresizingMaskIntoConstraints  = false
    mask.backgroundColor = .green
    mask.layer.cornerRadius = 50
    view.addSubview(mask)
    mask.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
    mask.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
    mask.widthAnchor.constraint(equalToConstant: 200).isActive = true
    mask.heightAnchor.constraint(equalToConstant: 100).isActive = true
    
    
    
    btn = UIButton()
    btn.backgroundColor = .red
    btn.translatesAutoresizingMaskIntoConstraints  = false
    btn.setTitle("More info", for: .normal)
    btn.tintColor = .black
    btn.addTarget(self, action: #selector(moreInfoTapped), for: .touchUpInside)
    
    
    view.addSubview(btn)
    btn.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
    btn.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
    btn.widthAnchor.constraint(equalToConstant: 200).isActive = true
    btn.heightAnchor.constraint(equalToConstant: 100).isActive = true
    
    
    view.layoutSubviews()
    view.setNeedsLayout()
    
    btn.mask = mask

This masks the button correctly but unfortunately the mask is placed in front of the button and thus taps on the button are never registered.

This is the view hierarchy:

Mask overlaying button

Am I missing something?


Solution

  • I dont know why you are masking for achieving round corners if you guide me i can suggest you better solution .. but for your current case if you turn off user interaction of mask view .. your button will start responding

    mask.isUserInteractionEnabled = false