Reputation: 733
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.
Upvotes: 6
Views: 2144
Reputation: 1760
Please note that in auto-layout environment systemLayoutSizeFittingSize
will not call even it change layout. It's a method to calculate the size of a view after view did finished layout.
The intrinsic content size is concerned only with data that is in the view itself, not in other views. Remember that you can also set constant width or height constraints on any view, and you don't need to override instrinsicContentSize if these dimensions won't be changing with changing view content
View will update it's content size if there is any update of it's constraint which is happened using - (void)updateConstraints
method that means you could override this method to observe the changes of it's constraints. Since you wants to rearrange views in certain width condition so best practice is to put on this - (void)layoutSubviews
method which will called on changes of view's frame.
- (void)layoutSubviews {
[super layoutSubviews];
// do your view arrangement based on width
// apple custom constraint here
}
Upvotes: 2
Reputation: 1529
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.
Upvotes: 7