在自定义单元格中获取标签的高度,以便在我的主视图控制器中使用heightForRowAt
我有一个视图控制器,使用一个名为searchCell自定义单元格带内容,我想知道如何获得标签lblLeft的高度,并在tableView(_ tableView:UITableView,heightForRowAt indexPath:IndexPath)中使用它 – > CGFloat函数返回标签的高度。 我在我的主视图控制器中使用的代码:
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 } }
在我的MHSearchCell中创build标签的代码的一部分,标签在这里连接成一个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 }
我使用自定义扩展来计算NSAttributedString的高度。 “containerWidth”将是您的标签的最大宽度,这很可能是您的单元格的contentView.bounds.size.width。
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) }
}
一个“技巧”是在cellForRowAtIndexPath之前调用heightForRowAtIndexPath。 您需要创build一个占位符单元格并保存对其的引用。 然后你做这样的事情:
// 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 }
您不希望在heightForRowAtIndexPath中初始化占位符单元格,因为每次调用该对象时,都会真正杀死您的性能以初始化对象。 这就是为什么你从头开始初始化它,并继续重用它。
//
如果你使用自动布局,你也可以看看如何让UITableView自动为你设置单元格的高度。 这可能是一个更好的select。
第一种方法要么使用自动尺寸
1)在标签上应用适当的限制检查下面的图像。
确保故事板中的标签行被设置为0
。
现在在控制器类中这样做:
//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 }
表格function – :
public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat{ return UITableViewAutomaticDimension }
另一种计算估计HeightForLabel的方法 –
1)如上所述对标签应用相同的约束
2)使用NSString的boundingRect
方法从标签中查找单元格的确切高度 – :
表视图function – :
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 }
记得-:
1)为标签提供相同的字体大小。
2)多行标签使用选项为.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 } }