'How to calculate height of a String?
I am trying to adjust the cell height resize to fit the UILabel text, but it is not working..
var mySize = CGFloat()
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! cellView
cell.myLabel.text = self.items[indexPath.item]
cell.myLabel.bounds.size.height = self.mySize
cell.backgroundColor = UIColor.yellowColor()
return cell
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
// handle tap events
print("You selected cell #\(indexPath.item)!")
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
func heightForLabel(text:String, font:UIFont, width:CGFloat) -> CGFloat
{
let label:UILabel = UILabel(frame: CGRectMake(0, 0, width, CGFloat.max))
label.numberOfLines = 0
label.lineBreakMode = NSLineBreakMode.ByWordWrapping
label.font = font
label.text = items[indexPath.row]
label.sizeToFit()
return label.frame.height
}
let font = UIFont(name: "Helvetica Neue", size: 30)
let detailHeight = heightForLabel(items[indexPath.row], font: font!, width: UIScreen.mainScreen().bounds.size.width)
self.mySize = detailHeight
return CGSizeMake(UIScreen.mainScreen().bounds.size.width, 358 + detailHeight)
}
Any suggestions what to do here? Should i do it another way? Please, I need help.. The problem is that the UILabel text is set in the cellForItemAtIndexPath, and items is an array for strings.
This is my project file, if someone watch to take a look at it: http://www.filedropper.com/test_37
Solution 1:[1]
Why not try this in ObjC
[text boundingRectWithSize:CGSizeMake(maxWidth, maxHeight)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:nil context:nil]
This will give CGRect. Get the height from it. set font size etc in attributes parameter.
UPDATE
In place of this
let detailHeight = heightForLabel(items[indexPath.row], font: font!, width: UIScreen.mainScreen().bounds.size.width)
Use this
let height = items[indexPath.row].boundingRectWithSize(CGSizeMake(CGFloat.max,UIScreen.mainScreen().bounds.size.width), options: .UsesLineFragmentOrigin, attributes: [NSFontAttributeName: font!], context: nil).size.height
Hope this helps
Solution 2:[2]
You can do it like that but I have implemented it in different way. Here is the sample of code you can do it.
let desiredWidth: CGFloat = tableView.bounds.size.width
let label: UILabel = UILabel()
let desiredString = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged."
label.text = desiredString
label.numberOfLines = 0;
label.lineBreakMode = NSLineBreakMode.ByWordWrapping
let size: CGSize = label.sizeThatFits(CGSizeMake(desiredWidth, CGFloat.max))
print("Label height you can set to your cell: \(size.height)")
Solution 3:[3]
I create this method for getting height of a label. You need to provide label's static Width and label's font
func dynamicHeight(font: UIFont, width: CGFloat) -> CGFloat{
let calString = NSString(string: self)
let textSize = calString.boundingRectWithSize(CGSizeMake(width, CGFloat.max), options: NSStringDrawingOptions.UsesLineFragmentOrigin|NSStringDrawingOptions.UsesFontLeading, attributes: [NSFontAttributeName: font], context: nil)
return textSize.height
}
Solution 4:[4]
Crate an String extension
extension String {
func heightOfString(usingFont font: UIFont) -> CGFloat {
let fontAttributes = [NSFontAttributeName: font]
let size = self.size(attributes: fontAttributes)
return size.height
}
}
get the height of the string as follows
let str = "Hello world"
let strHgt = str.heightOfString(usingFont: UIFont.systemFont(ofSize: 12))
Solution 5:[5]
Try this...
NSString *yourText = @"Your string";
CGSize lableWidth = CGSizeMake(300, CGFLOAT_MAX);
CGSize requiredSize = [yourText sizeWithFont:[UIFont fontWithName:@"CALIBRI" size:17] constrainedToSize:lableWidth lineBreakMode:NSLineBreakByWordWrapping];
int calculatedHeight = requiredSize.height;
return (float)calculatedHeight;
Solution 6:[6]
I took a look at your code, and I was able to solve it.
Firstly, on line 71 in your ViewController class:
let height = items[indexPath.row].boundingRectWithSize(CGSizeMake(CGFloat.max, UIScreen.mainScreen().bounds.size.width), options: .UsesLineFragmentOrigin, attributes: [NSFontAttributeName: font!], context: nil).size.height
You accidentally set CGFloat.max as width and the width as height. It should be:
CGSizeMake(UIScreen.mainScreen().bounds.size.width, CGFloat.max)
I'd say it's better practice to use the width of the view that the cell is directly contained in (the collectionView), but that's just my personal opinion.
Secondly, you need to enable AutoLayout. Go to your Main.storyboard file and make sure Use Auto Layout is selected.
Now you need to add constraints. (You can read more about AutoLayout and constraints here)
There are different ways to add constraints. The easiest way is to control click a UI element and drag the mouse to the element you want to set a constraint to.
You need to add the following constraints for your cell:
ImageView.top = cell.top
ImageView.leading = cell.leading
ImageView.trailing = cell.trailing
ImageView.bottom = MyLabel.top + 8 (your padding)
MyLabel.leading = cell.leading
MyLabel.trailing = cell.trailing
MyLabel.bottom = cell.bottom
And these for your CollectionView
CollectionView.top = view.top
CollectionView.leading = view.leading
CollectionView.trailing = view.trailing
CollectionView.bottom = view.bottom
I've attached the project, modified with AutoLayout here below.
Edit:
Approach 2 - without AutoLayout.
This could also be achieved without using AutoLayout by manually updating the cell's label height in collectionView:willDisplayCell:. I'm sure there are better alternatives, I'd personally try AutoResizingMasks before this approach.
Solution 7:[7]
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: [NSFontAttributeName: font], context: nil)
return ceil(boundingBox.height)
}}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | Chetan Purohit |
| Solution 3 | |
| Solution 4 | Ganesh Manickam |
| Solution 5 | kalpesh |
| Solution 6 | |
| Solution 7 | Jawad Ali |

