如何计算字符串的高度?

时间:2023-02-01 07:56:10

I am trying to adjust the cell height resize to fit the UILabel text, but it is not working..

我试图调整单元格高度调整大小以适应UILabel文本,但它不工作..

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.

有什么建议在这做什么?我应该用另一种方式吗?请问我需要帮助..问题是UILabel文本是在cellForItemAtIndexPath中设置的,而items是一个字符串数组。

This is my project file, if someone watch to take a look at it: http://www.filedropper.com/test_37

这是我的项目文件,如果有人注意看看它:http://www.filedropper.com/test_37

7 个解决方案

#1


4  

Why not try this in ObjC

为什么不在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.

这将给CGRect。从它获得高度。在attributes参数中设置字体大小等。

UPDATE

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

希望这可以帮助

#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)")

#3


1  

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
}

#4


0  

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;

#5


0  

I took a look at your code, and I was able to solve it.

我看了你的代码,我能够解决它。

Firstly, on line 71 in your ViewController class:

首先,在ViewController类的第71行:

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:

您不小心将CGFloat.max设置为宽度,将宽度设置为高度。它应该是:

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.

我想说使用单元格直接包含在(collectionView)中的视图宽度是更好的做法,但这只是我个人的看法。

Secondly, you need to enable AutoLayout. Go to your Main.storyboard file and make sure Use Auto Layout is selected.

其次,您需要启用AutoLayout。转到Main.storyboard文件,确保选中“使用自动布局”。

如何计算字符串的高度?

Now you need to add constraints. (You can read more about AutoLayout and constraints here)

现在您需要添加约束。 (您可以在此处阅读有关AutoLayout和约束的更多信息)

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.

有不同的方法来添加约束。最简单的方法是控制单击UI元素并将鼠标拖动到要设置约束的元素。

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

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.

我已经附加了项目,使用下面的AutoLayout进行了修改。

Modified project

修改项目

Edit:

编辑:

Approach 2 - without AutoLayout.

方法2 - 没有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.

这也可以通过在collectionView:willDisplayCell:中手动更新单元格的标签高度而不使用AutoLayout来实现。我确信有更好的选择,我会在这种方法之前亲自尝试AutoResizingMasks。

Project without AutoLayout

没有AutoLayout的项目

#6


0  

extension String{

extension String {

func height(withConstrainedWidth width: CGFloat, font: UIFont) -> CGFloat {

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)
}}

#7


0  

Crate an String extension

Crate一个String扩展

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))

#1


4  

Why not try this in ObjC

为什么不在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.

这将给CGRect。从它获得高度。在attributes参数中设置字体大小等。

UPDATE

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

希望这可以帮助

#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)")

#3


1  

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
}

#4


0  

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;

#5


0  

I took a look at your code, and I was able to solve it.

我看了你的代码,我能够解决它。

Firstly, on line 71 in your ViewController class:

首先,在ViewController类的第71行:

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:

您不小心将CGFloat.max设置为宽度,将宽度设置为高度。它应该是:

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.

我想说使用单元格直接包含在(collectionView)中的视图宽度是更好的做法,但这只是我个人的看法。

Secondly, you need to enable AutoLayout. Go to your Main.storyboard file and make sure Use Auto Layout is selected.

其次,您需要启用AutoLayout。转到Main.storyboard文件,确保选中“使用自动布局”。

如何计算字符串的高度?

Now you need to add constraints. (You can read more about AutoLayout and constraints here)

现在您需要添加约束。 (您可以在此处阅读有关AutoLayout和约束的更多信息)

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.

有不同的方法来添加约束。最简单的方法是控制单击UI元素并将鼠标拖动到要设置约束的元素。

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

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.

我已经附加了项目,使用下面的AutoLayout进行了修改。

Modified project

修改项目

Edit:

编辑:

Approach 2 - without AutoLayout.

方法2 - 没有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.

这也可以通过在collectionView:willDisplayCell:中手动更新单元格的标签高度而不使用AutoLayout来实现。我确信有更好的选择,我会在这种方法之前亲自尝试AutoResizingMasks。

Project without AutoLayout

没有AutoLayout的项目

#6


0  

extension String{

extension String {

func height(withConstrainedWidth width: CGFloat, font: UIFont) -> CGFloat {

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)
}}

#7


0  

Crate an String extension

Crate一个String扩展

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))