Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is a correct way to report desired size for UIView subclass?

Tags:

ios

swift

uiview

I am subclassing UIView and cannot find a right way to request/report its desired size. I expected systemLayoutSizeFittingSize to do the trick, but it is never called. Layout is simple - I pin top and leading of my view and limit trailing and bottom to be less than or equal to top-level view. Among all sizing functions, only intrinsicContentSize is called, but that one is not very helpful.

import Foundation
import UIKit

class StatsView: UIView
{
  override func drawRect(rect: CGRect)
  {
    let context=UIGraphicsGetCurrentContext()!
    CGContextSetRGBFillColor(context, 0, 0, 1, 1)
    CGContextFillRect(context, rect)
  }

  override func sizeThatFits(size: CGSize) -> CGSize
  {
    print("Called sizeThatFits with \(size)")
    if(size.width>350)
    {
      return CGSize(width: 350,height: 50)
    }
    else
    {
      return CGSize(width: 50,height: 100)
    }
  }

  override func systemLayoutSizeFittingSize(size: CGSize) -> CGSize
  {
    print("Called systemLayoutSizeFittingSize with \(size)")
    return super.systemLayoutSizeFittingSize(size)
  }

  override func systemLayoutSizeFittingSize(size: CGSize, withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority, verticalFittingPriority: UILayoutPriority) -> CGSize
  {
    print("Called systemLayoutSizeFittingSize with \(size)")
    if(size.width>350)
    {
      return CGSize(width: 350,height: 50)
    }
    else
    {
      return CGSize(width: 50,height: 100)
    }
  }

  override func intrinsicContentSize() -> CGSize
  {
    super.intrinsicContentSize()
    print("Called intrinsicContentSize")
    return CGSize(width: 10,height: 50)
  }
}

What is a right way to do it?

Update I want my view to have some info, not just a blue rectangle. There is some "optimal" width, but if the view cannot have that much from its parent, it can compensate by rearranging information to use more height. So, reporting constant values from intrinsicContentSize does not fit my needs.

like image 561
Dmitry Avatar asked Sep 30 '15 09:09

Dmitry


1 Answers

You use intrinsicContentSize to report the desired size of your view based off of it's contents. This value can change as the contents change, but you need to call invalidateIntrinsicContentSize when it does.

This intrinsicContentSize works along with contentHuggingPriority, contentCompressionResistancePriority, and the other layout constraints in the superview to determine the actual layout size.

In your case it sounds like you want to report an ideal size based off of the contents of your view, change the size and invalidate it if the content changes, and use layout constraints with sibling views and the parent view to compress (or resist) as needed.

like image 145
Scott H Avatar answered Oct 10 '22 17:10

Scott H