gasparuff
gasparuff

Reputation: 2295

Get height of UIView based on specific width before showing view

I have a UIView which I have designed in Interface Builder. It basically consists out of a header image and some text (UILabel) below. The view is being shown modally with a custom Transition and doesn't fill the whole screen.

There is like a 20 pixels margin on the left and right and 40 px on the top. The UILabel gets filled with some text that's coming from the web. What I want do do, is to find (or should I say predict) the height of the whole view for a specific width. How can I do that?

Upvotes: 1

Views: 3839

Answers (3)

sash
sash

Reputation: 8715

I had similar problem, but instead of calculating font size and image height you can use this UIView extension that will autosize your view with max width:

extension UIView {

    func autosize(maxWidth: CGFloat) {

        translatesAutoresizingMaskIntoConstraints = false

        let dummyContainerView = UIView(frame: CGRect(x: 0, y: 0, width: maxWidth, height: 10000000))
        dummyContainerView.addSubview(self)
        dummyContainerView.topAnchor.constraint(equalTo: topAnchor, constant: 0).isActive = true
        dummyContainerView.leftAnchor.constraint(equalTo: leftAnchor, constant: 0).isActive = true
        dummyContainerView.rightAnchor.constraint(equalTo: rightAnchor, constant: 0).isActive = true

        setNeedsLayout()
        layoutIfNeeded()

        removeFromSuperview()

        frame = CGRect(x: 0, y: 0, width: frame.width, height: frame.height)

        translatesAutoresizingMaskIntoConstraints = true
    }
} 

Using this approuch you don't have to worry about your content inside the view.

To use it:

let customView: CustomView = ... //create your view
... // configure all data on your view, e.g. labels with correct text
customView.autosize(maxWidth: 150) // resize your view 
view.addSubview(customView) // add your view to any view

Upvotes: 2

Alberto Scampini
Alberto Scampini

Reputation: 798

You need to have both the picture and the label before calculating the aspected size. I guess you should use something like this (maybe adding the vertical inter-distance between the imageView and the Label to the sum, and maybe removing the lateral margins from the width):

objective C :

- (CGFloat)preferredHeightFromWidth:(CGFloat)width text:(NSString *)text font:(UIFont *)font image:(UIImage *)image
{
    // Calculate label height
    CGFloat labelHeight = [text
                           boundingRectWithSize:CGSizeMake(width, 10000)
                           options:NSStringDrawingUsesLineFragmentOrigin
                           attributes:@{NSFontAttributeName:font}
                           context:[[NSStringDrawingContext alloc] init]
                           ].size.height;

    // Calculate image height
    CGFloat ratio = image.size.height/ image.size.width;
    CGFloat imageHeight = (ratio * width);

    // Do the sum
    return labelHeight + imageHeight;
}

Swift:

func preferredHeight(width: CGFloat, text: NSString, font: UIFont, image: UIImage) -> CGFloat {
    // Calculate Label Height
    let labelRect = text.boundingRect(
        with: CGSize.init(width: width, height: 10000),
        options: .usesLineFragmentOrigin,
        attributes: [NSFontAttributeName : font],
        context: NSStringDrawingContext())
    let labelHeight = labelRect.height

    // Calculate Image Height
    let ratio = image.size.height / image.size.width
    let imageHeight = ratio / width

    // Calculate Total Height
    let height = labelHeight + imageHeight

    // Return Height Value
    return height
}

(Thanks to Christopher Hannah for swift version)

Upvotes: 1

Christopher Hannah
Christopher Hannah

Reputation: 1748

Here is the same answer as Alberto, but I have changed it into Swift 3.

func preferredHeight(width: CGFloat, text: NSString, font: UIFont, image: UIImage) -> CGFloat {
    // Calculate Label Height
    let labelRect = text.boundingRect(
        with: CGSize.init(width: width, height: 10000),
        options: .usesLineFragmentOrigin,
        attributes: [NSFontAttributeName : font],
        context: NSStringDrawingContext())
    let labelHeight = labelRect.height

    // Calculate Image Height
    let ratio = image.size.height / image.size.width
    let imageHeight = ratio / width

    // Calculate Total Height
    let height = labelHeight + imageHeight

    // Return Height Value
    return height
}

Upvotes: 0

Related Questions