getting the height of a label in custom cell to use for heightForRowAt in my main view controller

余生颓废 提交于 2019-12-25 00:53:18

问题


I have a view controller that uses a custom cell called searchCell to bring content in and I am wondering how I can get the height of the label lblLeft and use it in the tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat function to return the height of the label. The code I'm using in my Main View Controller:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: 
    IndexPath) -> UITableViewCell {
    if searchMode == searching {
        let cell: MHSearchCell = tableView.dequeueReusableCell(withIdentifier: 
        MHSearchCell.ReusableIdentifier()) as! MHSearchCell

        cell.helper = helpers[indexPath.row]
        cell.delegate = self

        return cell
  }
}

Part of the code that creates the label in my MHSearchCell, the label is connected here as an IBOutlet:

lblLeft.text = ""

        if let expertiseCount = helper.expertise {

            let paragraphStyle = NSMutableParagraphStyle()
            paragraphStyle.lineSpacing = 5
            paragraphStyle.lineBreakMode = .byWordWrapping
            paragraphStyle.alignment = NSTextAlignment.center
            lblLeft.numberOfLines = 0

            let finalString = expertiseCount.map({$0.name!}).joined(separator: "   \u{00B7}   ")
            let finalAttributedString = NSMutableAttributedString(string: finalString, attributes: [NSParagraphStyleAttributeName:paragraphStyle])
            lblLeft.attributedText = finalAttributedString
        }

回答1:


First Way either use Automatic Dimensions

1) Apply Appropriate constraints on label check the image below.

Make sure label Lines are set to 0 in storyboard.

Now in controller class do this-:

//MArk-: ViewDidLoad
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        yourTableView.estimatedRowHeight = 142.0 // Default cell height from storyboard

        yourTableView.rowHeight = UITableViewAutomaticDimension
    }

Table Function-:

 public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat{
 return UITableViewAutomaticDimension
    }

Another Way of calculating estimatedHeightForLabel-:

1) Apply same constraints to label as mentioned above

2) use boundingRect method of NSString to find exact height for cell from label -:

Table View Functions-:

extension ViewController : UITableViewDelegate,UITableViewDataSource{
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
        return value.count
    }


    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as? testingCell
        cell?.textlabel.text = value[indexPath.row]
        return cell!
    }

    // Number of sections in table

    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }// Default is 1 if not implemented

    public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat{
        let text = value[indexPath.row]
        let estimatedheight = calculateEstimatedHeight(text: text)
        return estimatedheight.height
    }

    func calculateEstimatedHeight(text:String) -> CGRect{
        let size = CGSize(width: view.frame.width, height: 1000)
        let options = NSStringDrawingOptions.usesFontLeading.union(.usesLineFragmentOrigin)
        let attribute = [NSFontAttributeName:UIFont.systemFont(ofSize: 17)]
        let estimatedHeight = NSString(string: text).boundingRect(with: size, options: options, attributes: attribute, context: nil)
        return estimatedHeight
    }

Remember-:

1) Provide same font size you have for label.

2) For multiline label use option as .usesLineFragmentOrigin.

CustomCellClass-:

import UIKit

class testingCell: UITableViewCell {

    @IBOutlet weak var textlabel: UILabel!

    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }

}



回答2:


I use a custom extension to calculate the height of NSAttributedString. The "containerWidth" would be the max width of your label, which is most likely the contentView.bounds.size.width of your cell.

extension NSAttributedString {

func height(containerWidth: CGFloat) -> CGFloat {
    let rect = self.boundingRect(with: CGSize.init(width: containerWidth, height: CGFloat.greatestFiniteMagnitude), options: [.usesLineFragmentOrigin, .usesFontLeading], context: nil)
    return ceil(rect.size.height)
}

func width(containerHeight: CGFloat) -> CGFloat {
    let rect = self.boundingRect(with: CGSize.init(width: CGFloat.greatestFiniteMagnitude, height: containerHeight), options: [.usesLineFragmentOrigin, .usesFontLeading], context: nil)
    return ceil(rect.size.width)
}

}

One "trick" is that heightForRowAtIndexPath is called before cellForRowAtIndexPath. You need to create a placeholder cell and keep a reference to it. Then you do something like this:

// Init this once and early
var searchCellPlaceholder = SearchCell() // Use whatever the default initializer is 

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    let object = data[indexPath.row]
    // Keep reusing this cell and populate it with the new object text, use the configure method in cellForRowAtIndex too.
    configureCell(cell: searchCellPlaceholder object: object)
    // Get the height of the label after the text was applied
    let height = searchCell.label.height(containerWidth: serachCell.contentView.bounds.size.width)

    return height
}

You don't want to init the placeholder cell in heightForRowAtIndexPath because it will really kill your performance to initialize an object every time that's called. That's why you initialize it from the beginning and keep reusing it.

//

If you're using auto layout, you can also look up how to have the UITableView automatically set the height of the cell for you. Which could be a better option.



来源:https://stackoverflow.com/questions/45680791/getting-the-height-of-a-label-in-custom-cell-to-use-for-heightforrowat-in-my-mai

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!