UITableViewCell高度不正确,sizeToFit大小不正确

时间:2015-07-11 00:06:56

标签: ios iphone swift uitableview

我正在尝试创建一个自定义的UITableViewCell,并且问题是具有适当高度的单元框架。这是令人不安的,因为运行iOS 8.4的iPhone 4s / 5s的单元尺寸正确,但运行相同操作系统的iPhone 6/6 +的尺寸不正确。

sizeToFit上调用messageLabel时会发生混乱。一些标签几乎看起来在下面有额外的空白行,但显然不像单元格那样高。

以下是自定义单元格。出现问题的标签是messageLabel。要查看标签的框架,let borders = true

//
//  NotesTableViewCell.swift
//  urchin
//
//  Created by Ethan Look on 6/17/15.
//  Copyright (c) 2015 Tidepool. All rights reserved.
//

import Foundation
import UIKit

let noteCellHeight: CGFloat = 128
let noteCellInset: CGFloat = 16
let labelSpacing: CGFloat = 6

class NoteCell: UITableViewCell {

    let borders = false

    var cellHeight: CGFloat = CGFloat()

    let usernameLabel: UILabel = UILabel()
    let timedateLabel: UILabel = UILabel()
    var messageLabel: UILabel = UILabel()

    func configureWithNote(note: Note) {

        usernameLabel.text = note.user!.fullName
        usernameLabel.font = UIFont(name: "OpenSans-Bold", size: 17.5)!
        usernameLabel.textColor = UIColor.blackColor()
        usernameLabel.sizeToFit()
        let usernameX = noteCellInset
        let usernameY = noteCellInset
        usernameLabel.frame.origin = CGPoint(x: usernameX, y: usernameY)

        let dateFormatter = NSDateFormatter()
        dateFormatter.dateFormat = "EEEE M.d.yy h:mm a"
        var dateString = dateFormatter.stringFromDate(note.timestamp)
        dateString = dateString.stringByReplacingOccurrencesOfString("PM", withString: "pm", options: NSStringCompareOptions.LiteralSearch, range: nil)
        dateString = dateString.stringByReplacingOccurrencesOfString("AM", withString: "am", options: NSStringCompareOptions.LiteralSearch, range: nil)
        timedateLabel.text = dateString
        timedateLabel.font = UIFont(name: "OpenSans", size: 12.5)!
        timedateLabel.textColor = UIColor.blackColor()
        timedateLabel.sizeToFit()
        let timedateX = contentView.frame.width - (noteCellInset + timedateLabel.frame.width)
        let timedateY = usernameLabel.frame.midY - timedateLabel.frame.height / 2
        timedateLabel.frame.origin = CGPoint(x: timedateX, y: timedateY)

        messageLabel.frame.size = CGSize(width: contentView.frame.width - 2 * noteCellInset, height: CGFloat.max)
        let hashtagBolder = HashtagBolder()
        let attributedText = hashtagBolder.boldHashtags(note.messagetext)
        messageLabel.attributedText = attributedText
        messageLabel.adjustsFontSizeToFitWidth = false
        messageLabel.lineBreakMode = NSLineBreakMode.ByWordWrapping
        messageLabel.numberOfLines = 0
        messageLabel.sizeToFit()
        let messageX = noteCellInset
        let messageY = usernameLabel.frame.maxY + 2 * labelSpacing
        messageLabel.frame.origin = CGPoint(x: messageX, y: messageY)

        contentView.addSubview(usernameLabel)
        contentView.addSubview(timedateLabel)
        contentView.addSubview(messageLabel)

        cellHeight = noteCellInset + usernameLabel.frame.height + 2 * labelSpacing + messageLabel.frame.height + noteCellInset

        if (borders) {
            usernameLabel.layer.borderWidth = 1
            usernameLabel.layer.borderColor = UIColor.redColor().CGColor

            timedateLabel.layer.borderWidth = 1
            timedateLabel.layer.borderColor = UIColor.redColor().CGColor

            messageLabel.layer.borderWidth = 1
            messageLabel.layer.borderColor = UIColor.redColor().CGColor

            self.contentView.layer.borderWidth = 1
            self.contentView.layer.borderColor = UIColor.blueColor().CGColor
        }

        self.contentView.frame.size = CGSize(width: self.contentView.frame.width, height: cellHeight)
    }  
}

heightForRowAtIndexPath

func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
       let cell = NoteCell(style: .Default, reuseIdentifier: nil)
       cell.configureWithNote(notes[indexPath.row])
       return cell.cellHeight
}

该项目是开源的on Github,所以请随意克隆存储库并自行检查所有代码。

谢谢!

2 个答案:

答案 0 :(得分:0)

很遗憾,您不能这样做,因为首先调用tableView(_:heightForRowAtIndexPath),并且您返回的值用于创建您将在tableView(_:cellForRowAtIndexPath)中出列的单元格。单元格无法设置自己的大小,因为在它可以执行此操作时(例如awakeFromNibprepareForResuse),表格视图已经具有高度值。我已经使用过一些令人讨厌的解决方法,但是使用自定义表格视图单元格更容易。

检查一下: http://www.appcoda.com/self-sizing-cells/

答案 1 :(得分:0)

我不是在heightForRowAtIndexPath:中创建一个全新的单元格,而是创建确定单元格高度的UI元素(usernameLabel和messageLabel),使用sizeToFit适当地调整它们的大小,然后进行简单的计算确定细胞高度。

通过这样做,我从未创建一个后来出列的新单元格。

func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {

    let usernameLabel = UILabel(frame: CGRectZero)
    usernameLabel.font = UIFont(name: "OpenSans-Bold", size: 17.5)!
    usernameLabel.text = notes[indexPath.row].user!.fullName
    usernameLabel.sizeToFit()

    let messageLabel = UILabel(frame: CGRect(x: 0, y: 0, width: self.view.frame.width - 2*noteCellInset, height: CGFloat.max))
    let hashtagBolder = HashtagBolder()
    let attributedText = hashtagBolder.boldHashtags(notes[indexPath.row].messagetext)
    messageLabel.attributedText = attributedText
    messageLabel.adjustsFontSizeToFitWidth = false
    messageLabel.lineBreakMode = NSLineBreakMode.ByWordWrapping
    messageLabel.numberOfLines = 0
    messageLabel.sizeToFit()

    let cellHeight = noteCellInset + usernameLabel.frame.height + 2 * labelSpacing + messageLabel.frame.height + noteCellInset

    return cellHeight
}