Home > OS >  When does a subview of a custom UIView know its own bounds?
When does a subview of a custom UIView know its own bounds?

Time:04-26

I've created a custom UIView with a subview containing several square subviews which are sized using layout constraints. I'd like for each subview to be circular so I'm holding a reference to the view in an array, then iterating through the array of views in the layoutSubviews method and applying a corner radius that is half the view.bounds.height.

image showing main view, content view, then three circular views inside

The problem is, this only works 70% of the time. Sometimes the view doesn't seem to know its bounds and the views are rendered as square.

image showing main view, content view, then three square views inside

I'm probably approaching this all wrong... does anyone have any advice for me? Where is it safe to apply the corner radius so that it always renders as a perfect circle?

Thanks

CodePudding user response:

The most reliable way to manage this is to subclass UIView and let it handle its own rounding.

For example:

class RoundView: UIView {
    override func layoutSubviews() {
        super.layoutSubviews()
        // this assumes constraints keep
        //  self at a 1:1 ratio (square)
        layer.cornerRadius = bounds.height * 0.5
    }
}

This simple controller example:

class RoundDemoVC: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let colors: [UIColor] = [
            .systemRed, .systemGreen, .systemBlue
        ]
        let widths: [CGFloat] = [
            200, 140, 140
        ]
        let xPos: [CGFloat] = [
            20, 120, 180
        ]
        let g = view.safeAreaLayoutGuide
        for i in 0..<colors.count {
            let v = RoundView()
            v.backgroundColor = colors[i]
            view.addSubview(v)
            v.translatesAutoresizingMaskIntoConstraints = false
            v.widthAnchor.constraint(equalToConstant: widths[i]).isActive = true
            // make it square
            v.heightAnchor.constraint(equalTo: v.widthAnchor).isActive = true
            v.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: xPos[i]).isActive = true
            v.centerYAnchor.constraint(equalTo: g.centerYAnchor).isActive = true
        }
        
    }
    
}

Produces this output:

enter image description here

No need to iterate through subviews and setting values based on frame sizes... all you need to do is set the size/position constraints.

CodePudding user response:

Donmag's example is cool.Also, you can do it this way without writing code to layoutsubview. You must add this settings after adding the constraints of the subviews in for iteration.

 .......
 ....... // constraint settings

 subView.layoutIfNeeded()
 subView.layer.cornerRadius = subView.frame.size.height/2
    

CodePudding user response:

override func layoutSubviews() {
    super.layoutSubviews()
    // This is the place to apply corner radius
}
  • Related