Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting size of UIView in init

I have made a custom subclass of UIView in my iOS application, and I am trying to get the computed sizes of the view in the view's init method, so I can use them when creating subviews to put inside the custom view.

The custom view is inside a stack view, which assigns my view 1/3 of the total (main view) height.

My init looks like this:

var mySubView: UIImageView

required init?(coder aDecoder: NSCoder) {

    mySubView = UIImageView()
    super.init(coder: aDecoder)

    let viewWidth = Int(self.frame.size.width)
    let viewHeight = Int(self.frame.size.height)
    mySubView.frame = CGRect(x: 0, y: 0, width: viewWidth, height: viewHeight)
    mySubView.backgroundColor = UIColor.cyan

    self.addSubview(mySubView)
}

However, the heights and widths are not reported correctly. For instance, mySubView above only ends up filling about half of the total space of the custom view.

Any help would be greatly appreciated!

like image 675
rcca Avatar asked Jan 07 '17 18:01

rcca


People also ask

What is UIView in Android?

An object that manages the content for a rectangular area on the screen. Views are the fundamental building blocks of your app's user interface, and the UIView class defines the behaviors that are common to all views. A view object renders content within its bounds rectangle, and handles any interactions with that content.

How do I animate a view in UIView?

Use the UIViewPropertyAnimator class to perform animations instead. class func animate(withDuration: TimeInterval, delay: TimeInterval, options: UIView.AnimationOptions, animations: () -> Void, completion: ( (Bool) -> Void)?) Animate changes to one or more views using the specified duration, delay, options, and completion handler.

What is the difference between UIView and a view object?

A view object renders content within its bounds rectangle and handles any interactions with that content. The UIView class is a concrete class that you can instantiate and use to display a fixed background color. You can also subclass it to draw more sophisticated content.

Can I override custom methods in UIView subclasses?

Because UIView is a highly configurable class, there are also many ways to implement sophisticated view behaviors without overriding custom methods, which are discussed in the Alternatives to Subclassing section. In the meantime, the following list includes the methods you might consider overriding in your UIView subclasses:


1 Answers

The initializer is called too early in the lifecycle of the view to accurately do layout unless you know the exact dimensions in advance. Even so, it is idiomatically the wrong place to do it.

Try using the layoutSubviews method as such:

class SubView: UIImageView {

    var mySubView: UIImageView

    required init?(coder aDecoder: NSCoder) {

        mySubView = UIImageView()
        mySubView.backgroundColor = UIColor.cyan

        super.init(coder: aDecoder)
        self.addSubview(mySubView)
    }

    override func layoutSubviews() {
        mySubView.frame = self.bounds
        super.layoutSubviews()
    }
}

Now the subview bounds will be set properly at the start of each layout pass. It’s a cheap operation.

Also, the bounds property of a UIView is the frame translated to the view’s internal coordinate space. This means that normally this is true: bounds = CGRect(x: 0, y: 0, width: frame.size.width, height: frame.size.height). I suggest reading the documentation on view layout.

Alternatively, you can ditch manual layout entirely and use AutoLayout to do this for you.

class SubView: UIImageView {

    var mySubView: UIImageView

    required init?(coder aDecoder: NSCoder) {

        mySubView = UIImageView()
        mySubView.backgroundColor = UIColor.cyan

        super.init(coder: aDecoder)
        self.addSubview(mySubView)

        mySubView.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
        mySubView.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
        mySubView.widthAnchor.constraint(equalTo: widthAnchor).isActive = true
        mySubView.heightAnchor.constraint(equalTo: heightAnchor).isActive = true
    }
}
like image 50
Adam Kaplan Avatar answered Oct 06 '22 19:10

Adam Kaplan