Problem with sizeToFit - autoSizing
proxzi opened this issue · comments
Hi all! Please help me solve the problem, in case someone has come across such a case: I’ll describe it briefly, I have many elements in my project that are pin using pinLayout, and there is a need to calculate the content size for a specific view, for example:
Let's say there is a TextItem element:
its implementation is like this
final class TextItem: UIView {
private var textView: UILabel
init(text: String) {
textView = UILabel()
textView.text = text
textView.font = .systemFont(ofSize: 14)
textView.numberOfLines = 0
textView.lineBreakMode = .byWordWrapping
super.init(frame: .zero)
addSubview(textView)
}
@available(*, unavailable, message: "init(coder:) has not been implemented")
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
performLayout()
}
override func sizeThatFits(_ size: CGSize) -> CGSize {
autoSizeThatFits(size, layoutClosure: performLayout)
}
private func performLayout() {
textView.pin
.sizeToFit(.width)
.all()
}
}
If you usually pin it into any view, then everything is okay, everything works, but I need to calculate the size of this view (that is, the label that is pinned with the PinLayout) based on the size of the content.
I want to do something like this (for a regular UILabel() this will all work like in your example "AdjustToContainer")
class ChoiceSelectorView: UIView {
private var textLeft = TextItem(text: "Левая часть")
private var textRight = TextItem(text: "правая частььььььььььььььььььььььььььь")
init() {
super.init(frame: .zero)
addSubview(textLeft)
addSubview(textRight)
textRight.sizeToFit()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
performLayout()
}
override func sizeThatFits(_ size: CGSize) -> CGSize {
autoSizeThatFits(size, layoutClosure: performLayout)
}
private func performLayout() {
textRight.pin.top().right().size(textRight.bounds.size).maxWidth(UIScreen.main.bounds.width*0.9)
textLeft.pin.top().left().before(of: textRight).sizeToFit(.width)
}
}
But for a TextItem element that is on pinLayout, sizeThatFits will return the length of the entire screen and the left label will displace the right one and fill the entire screen.
textRight.sizeThatFits(UIScreen.main.bounds.size) -> return screen width
I also tried to specify sizeToFit(.widthFlexible) for TextItem, but then for this case, cutting the line will not work, that is, if numberOfLine = 1, then at the end of the 3rd dot will not appear, and this change may break all other views in which there is a TextItem, and they are already laid out.
Maybe you have some options with pinLayout, how you can correctly calculate the size of a TextItem so that it is calculated only by the size of the text itself.
Thanks.
its solve like this in TextItem:
override func sizeThatFits(_ size: CGSize) -> CGSize {
textView.sizeThatFits(size)
}
private func performLayout() {
textView.frame = bounds
}