Calculate height of UICollectionViewCell dynamically in Swift - ios

I am having 2 labels which i need to add on each UICollectionViewCell. These 2 labels have the different text. I need to calculate the height of UICollectionViewCell depending upon these labels Height. How can i do that?

Use this extension
extension UILabel {
var size: CGFloat {
let rect = NSString(string: self.text!).boundingRectWithSize(CGSize(width: self.frame.width, height: CGFloat(MAXFLOAT)), options: .UsesLineFragmentOrigin, attributes: [NSFontAttributeName: self.font], context: nil)
return ceil(rect.height)
}
}

Related

UILabel and .usesFontLeading

I researched a bit and it looks like the default value for NSLayoutManager's .usesFontLeading value is true.
My problem:
I'm using boundingRect to get the size of the text in UILabel with a custom font, the height is correct if I remove .usesFontLeading but incorrect if I add that option.
My question:
In UILabel, does the font of my label automatically use my font's leading value? and secondly, am I required to set .usesFontLeading as an option in my boundingRect.
Try this:
extension String {
func height(withConstrainedWidth width: CGFloat, font: UIFont) -> CGFloat {
let constraintRect = CGSize(width: width,
height: .greatestFiniteMagnitude)
let boundingBox = self.boundingRect(with: constraintRect,
options: [.usesLineFragmentOrigin, .usesFontLeading],
attributes: [.font: font],
context: nil)
return ceil(boundingBox.height)
}
}

Uilabel height using boundigRect

Hi everyone I have created a view that shows an error message. Within this view I have inserted a UILabel that shows the message. So far so good, the height of the UILabel changes based on the length of the text using text.boundingRect
My problem is that the text is shown correctly only if it does not exceed a certain number of lines, in case the text is too long it is cut and I don't understand why
In short, if the text is not very long I have no display problems otherwise if the text is very long it is cut
this is what i am using to get the height of the text.
Where am I wrong?
private func estimateTextHeight()-> CGFloat {
let text = (toastView.textLbl.text ?? "") as NSString
let attribute: [NSAttributedString.Key: Any] = [.font: toastView.textLbl.font!]
return text.boundingRect(with: .init(width: 300, height: 2000), options: .usesLineFragmentOrigin, attributes: attribute, context: nil).height
}
private func updateToast(icon: UIImage?) -> Void {
let height = estimateTextHeight()
toastView.heightAnchor.constraint(equalToConstant: height).isActive = true
}
To calculate label height try this:
extension String {
func height(withConstrainedWidth width: CGFloat, font: UIFont) -> CGFloat {
let constraintRect = CGSize(width: width,
height: .greatestFiniteMagnitude)
let boundingBox = self.boundingRect(with: constraintRect,
options: .usesLineFragmentOrigin,
attributes: [.font: font],
context: nil)
return ceil(boundingBox.height)
}
}

Inconsistent behavior with number of actual lines calculation for UILabel in IOS with Swift

I am using the below UILabel extension method to calculate the number of actual lines in the UILabel. However, I see that it always returns more than the actual number of lines. Moreover, the excess number of lines it returns is not the same always. So, I cannot subtract it with a fixed constant before using the value. Any thoughts of what is wrong here. I have already looked at the solutions posted in stack overflow but they did not help either.
extension UILabel {
var maxNumberOfLines: Int {
guard let text = text, let font = font else {
return 0
}
let charSize = font.lineHeight
let textSize = (text as NSString).boundingRect(
with: CGSize(width: frame.width, height: .greatestFiniteMagnitude),
options: .usesLineFragmentOrigin,
attributes: [.font: font],
context: nil)
let linesRoundedUp = Int(ceil(textSize.height/charSize))
return linesRoundedUp
}
}
Since I was trying to find the number of lines for UILabel in cell for row at index path delegate method, I was getting wrong result as the UILabel would not be laid out in the tableview cell yet. I used UIScreen.main.bounds - some offset in place of label width for number of lines calculation and that solved the issue.
To be precise, I used
extension UILabel {
var maxNumberOfLines: Int {
guard let text = text, let font = font else {
return 0
}
let charSize = font.lineHeight
let textSize = (text as NSString).boundingRect(
with: CGSize(width: UIScreen.main.bounds.width - SOMEOFFSET, height: .greatestFiniteMagnitude),
options: .usesLineFragmentOrigin,
attributes: [.font: font],
context: nil)
let linesRoundedUp = Int(ceil(textSize.height/charSize))
return linesRoundedUp
}
}

Default line spacing of UILabel

What is default line spacing in UILabel. I need to calculate how many lines can be in UILabel with set frame.
I'm not sure what the default line spacing is in a UILabel, but I used the below to calculate the number of lines a UILabel wants to be.
extension UILabel {
var preferredNumberOfLines: Int {
guard let currentText = self.text else {
return 0
}
let labelSize = currentText.boundingRect(with: CGSize(width: self.bounds.width,
height: CGFloat.greatestFiniteMagnitude),
options: NSStringDrawingOptions.usesLineFragmentOrigin,
attributes: [NSAttributedStringKey.font : self.font],
context: nil)
return Int(ceil(CGFloat(labelSize.height) / self.font.lineHeight))
}
}

get height of dynamic textViews in tableView without using automatic dimensions using swift

I want to calculate the height of my textView's in a tableView dynamically to use in heightForRowAt. I DO NOT want to use automatic dimensions as it often messes up my scrolling in containerViews.
Presently I am instantiating a textView for every cell, adding the text and getting the height using:
var textViewForCellHeight = UITextView()
textViewForCellHeight.font = UIFont.preferredFont(forTextStyle: UIFontTextStyle.body)
textViewForCellHeight.frame = CGRect(x: 0, y: 0, width: self.tableView.frame.size.width - cellHorizontalPadding - tableView.safeAreaInsets.left - tableView.safeAreaInsets.right, height: 0)
textViewForCellHeight.text = myString
textViewForCellHeight.sizeToFit()
return textViewForCellHeight.frame.size.height
Using this in heightForRowAt works fine and gives the correct height for the cell, but it expensive and slows down the tableView considerably. Is there a more efficient way to get the height of the tableView cell's dynamically with a textView?
You can simply pass your string in this function and you will get dynamic height according to your string.
func calculateHeight(inString:String) -> CGFloat
{
let messageString = input.text
let attributes : [NSAttributedStringKey : Any] = [NSAttributedStringKey(rawValue: NSAttributedStringKey.font.rawValue) : UIFont.systemFont(ofSize: 15.0)]
let attributedString : NSAttributedString = NSAttributedString(string: messageString!, attributes: attributes)
let rect : CGRect = attributedString.boundingRect(with: CGSize(width: 222.0, height: CGFloat.greatestFiniteMagnitude), options: .usesLineFragmentOrigin, context: nil)
let requredSize:CGRect = rect
return requiredSize.height
}
Try this code:
func cellHeight(withTxt string: String) -> Float {
let textRect: CGRect = string.boundingRect(with: CGSize(width: self.view.frame.width/* Preferred textView Width */, height: CGFloat(MAXFLOAT)), options: ([.usesLineFragmentOrigin, .usesFontLeading]), attributes: [.font: UIFont(name: "Helvetica Neue", size: 17)!], context: nil)
let requiredSize: CGSize = textRect.size
//finally u return your height
return Float(requiredSize.height)
}

Resources