0

I have a base UIView that has a visualEffectView as it's subview. I set the visualEffectView's view frame.height as 80. When presenting to ViewController, I want to reset its height to 120. Currently, when presented, the height is initially 120 but then quickly clips back down to 80. Shouldn't my frame in my ViewController override the frame set in the UIView? My frame in the ViewController gets called first but later it gets called from the UIView, causing the clipping bug.

class CardView: UIView {

let visualEffectView = UIVisualEffectView(effect: UIBlurEffect(style: .light))

override init(frame: CGRect) {
    super.init(frame: frame)
    clipsToBounds = true
    addSubview(visualEffectView)
}

override func layoutSubviews() {
    super.layoutSubviews()

    visualEffectView.anchor(top: topAnchor, left: leftAnchor, bottom: nil, right: rightAnchor, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: 0, height: 80)

  }
}

class ViewController: ViewController {

let cardView: CardView = {
    let cv = CardView()
    cv.imageView.clipsToBounds = true
    cv.layer.cornerRadius = 18
    return cv
}()

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    let superviewFrame = view.frame.height
    cardView.frame = CGRect(x: 10, y: superviewFrame / 8, width: view.frame.width - 20, height: superviewFrame - (superviewFrame / 5))
    cardView.visualEffectView.anchor(top: cardView.topAnchor, left: cardView.leftAnchor, bottom: nil, right: cardView.rightAnchor, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: 0, height: 120)     
  }
}
Bhaumik
  • 1,218
  • 1
  • 11
  • 20
Kenny Ho
  • 409
  • 3
  • 16
  • try setting `cardView.visualEffectView.translatesAutoresizingMaskIntoConstraints` to false, or ditch the whole frame approach and use constraints instead. – Sander Saelmans Mar 28 '19 at 16:06
  • You refer to your constraints in your question, but you aren't using any. Your code doesn't make any use of auto layout, which it should. Furthermore, subclassing `UIView` can be an involved process and I would suggest reading https://stackoverflow.com/questions/15978370/proper-practice-for-subclassing-uiview You'll probably want to make use of the `updateConstraints` lifecycle method in the custom view. – trndjc Mar 28 '19 at 16:10
  • when using anchor constraints, the size doesn't even adjust. – Kenny Ho Mar 28 '19 at 16:11
  • my apologies I'm still learning the lingo. I thought setting the frame's height was a constraint. – Kenny Ho Mar 28 '19 at 16:13
  • No worries. When positioning and sizing a view, you want to try and avoid doing it in the view's frame property. Let auto layout do it for you. – trndjc Mar 28 '19 at 16:17
  • I edited the code to use constraints. but the the visual effect's height doesn't even change like it does for frame. I tried setting it in updateViewConstraints() but it also doesn't do anything. – Kenny Ho Mar 28 '19 at 16:20
  • You've got a lot going on here and you have a lot to learn before you should be subclassing `UIView`, IMO. Start with a blank view controller and just add a plain view to it (forget subclassing for a moment). Learn the lifecycle of `UIViewController` and which methods get called when. Learn how auto layout works and how to properly add constraints. Then try to manipulate that plain view to do what you want it to do. Once you're comfortable with that, then get into subclassing views. Really take the iOS framework one step at a time because it can become overwhelming. – trndjc Mar 28 '19 at 16:27
  • Also learn the terminology. When you say present, for example, that has a specific meaning in UIKit; it means to modally present a view controller from another. Also, establish general rules when working with objects and which objects should have dominion over others. For example, if your view controller is displaying a view with an initial height of 80, which object should be responsible for setting that value, the view controller or the view itself? You set your custom view's corner radius in the view controller, but shouldn't the view determine its own styling? – trndjc Mar 28 '19 at 16:31
  • the reason why i set it in the ViewController is because I use the UIView in multiple ViewControllers. But in each ViewController it's slightly different. I'm trying to reuse code as much as I can. I ran into this problem and was just curious what was happening. – Kenny Ho Mar 28 '19 at 16:38

2 Answers2

0

try moving this code

visualEffectView.anchor(top: topAnchor, left: leftAnchor, bottom: nil, right: rightAnchor, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: 0, height: 80)

from override func layoutSubviews() { to override init(frame: CGRect) {

after super.init()

Joshua Cleetus
  • 624
  • 6
  • 14
0

You may need a guard condition and if there is a constraint, just pass.

    override func layoutSubviews() {
    super.layoutSubviews()

    guard visualEffectView.constraintsAffectingLayout(for: .vertical).count == 0 else  {return}. // Here

    visualEffectView.anchor(top: topAnchor, left: leftAnchor, bottom: nil, right: rightAnchor, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: 0, height: 80)
}
E.Coms
  • 11,065
  • 2
  • 23
  • 35