0

I have a UIButton that I'm giving a blurred and darkened background. When I highlight it (press it but don't release on-button), however, it loses its transparency by what seems to be non-transparent layers being added.

Here's a video of it; the problem starts a few seconds in: https://i.stack.imgur.com/xgZwY.jpg

My custom button class looks like this:

override func layoutSubviews() {
    super.layoutSubviews()
    let blur = UIVisualEffectView(effect: UIBlurEffect(style: .regular))
    blur.frame = self.bounds
     blur.isUserInteractionEnabled = false
     self.insertSubview(blur, at: 0)
}

Building with: Swift 4, iOS 12 beta

What is the problem here and what's the best way to fix it?

  • Please read [mcve] and then [edit] your question showing the _minimum_ code that demonstrates the problem - a working example, removing references to code we can't see, or code that doesn't effect the issue at hand. – Ashley Mills Sep 09 '18 at 19:55
  • Is your button created in code, or in a storyboard? – Ashley Mills Sep 09 '18 at 20:07
  • It's in a storyboard. The issue was using layoutSubviews(), because it's called multiple times during the lifetime of the button. Answer below reflects that. – afishershin Sep 09 '18 at 20:10

2 Answers2

3

As you mention, layoutSubviews is called multiple times.

As your button is created in a storyboard, you could move the code to add the blur to

func awakeFromNib()

this method is only called once per object that's created from a xib or storyboard file,

You should layout the UIVisualEffectView using autolayout (adding layout constraints), or adjust it's frame only in layoutSubviews()

Ashley Mills
  • 50,474
  • 16
  • 129
  • 160
0

layoutSubviews() is called multiple times, including when the button is highlighted. Consequently, the blur is added each time. I added logic to prevent this, fixing the problem. New code:

var isBlurred = false

override func layoutSubviews() {
    super.layoutSubviews()
    if !isBlurred {
        let blur = UIVisualEffectView(effect: UIBlurEffect(style:
            .regular))
        blur.frame = self.bounds
        blur.isUserInteractionEnabled = false
        self.insertSubview(blur, at: 0)
        isBlurred = true
    }
}

It's a little quick-and-dirty, but it fixes the issue.