自定义表格视图单元格中UILabel中的行数

雅各布

编辑2-我能够通过使用在不同问题(https://stackoverflow.com/a/14413484/2584268)中找到的不同方法来使其工作,但是我还将其与GeneratorOfOne提供的代码结合在一起,并且我在下面发布了我的结果。但是,我仍然对此最终目标有疑问。目标是在每一行文本旁边都有行号,就像在代码编辑器中一样。问题是我需要保持连续的行数,因此,如果第一个单元格中有3行,则第二个单元格中的行号应从4开始,依此类推,但是我不相信我可以这样做因为正在计算单元格中的行数,所以我无法将值返回到tableview来设置第二个标签的文本(行号)...有什么想法吗?

override func layoutSubviews() {
        super.layoutSubviews()
        calculateNumberOfLines()
    }

    var textDetail: String?  {
        didSet {
            gameInfo.text = textDetail
        }
    }

    func calculateNumberOfLines() {

        let layoutManager = NSLayoutManager()

        let textStorage = NSTextStorage(string: self.gameInfo!.text!)
        textStorage.addAttribute(NSFontAttributeName, value: self.gameInfo!.font, range: NSMakeRange(0, textStorage.length))

        let textContainer = NSTextContainer(size: CGSize(width:self.contentView.bounds.size.width - 56.0, height: CGFloat.max))
        layoutManager.addTextContainer(textContainer)
        layoutManager.textStorage = textStorage
        if let text = gameInfo?.text {

            let numberOfLines = getLinesArrayOfStringInLabel(gameInfo)
            lineNumbers.text = "\(startingNum)"
            for index in startingNum+1...startingNum+numberOfLines {

                lineNumbers.text = lineNumbers.text?.stringByAppendingString("\n\(index)")

            }

            endingNum = startingNum+numberOfLines
            //let numberOfLines = totalNumberOfLinesIn(text, currentGlyphIndex:0, currentLineNumber: 1, layoutManager: layoutManager, textContainer: textContainer)
            //lineNumbers.text = "\(numberOfLines)"

        } else { return }


    }

    func getLinesArrayOfStringInLabel(label: UILabel) -> Int {

        var text = label.text as! NSString
        var font = label.font
        var rect = label.frame

        var myFont = CTFontCreateWithName(font.fontName, font.pointSize, nil)
        var attrString = NSMutableAttributedString(string: text as String)
        attrString.addAttribute(String(kCTFontAttributeName), value: myFont, range: NSMakeRange(0, attrString.length))

        let frameSetter = CTFramesetterCreateWithAttributedString(attrString)

        var path = CGPathCreateMutable()
        CGPathAddRect(path, nil, CGRectMake(0,0,rect.size.width,100000))
        var frame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, 0), path, nil)

        var lines = CTFrameGetLines(frame) as NSArray
        var linesArray = NSMutableArray()

        for line in lines as [AnyObject] {

            var lineRef = line as! CTLineRef
            var lineRange = CTLineGetStringRange(lineRef)
            var range = NSMakeRange(lineRange.location, lineRange.length)

            var lineString = text.substringWithRange(range)
            linesArray.addObject(lineString)

        }

        return linesArray.count
    }

我有一个自定义UITableViewCell子类,该子类正在使用自动调整大小的单元格。单元的大小是完美的,并且标签已正确扩展。但是,在运行时,我试图计算标签将扩展到的行数(我需要在标签旁边显示行号),但我无法实现这一点。我尝试了以下两种方法,但似乎都没有返回运行该应用程序时看到的正确行数:

func lineCountForText(string: String, label: UILabel) -> Int {

        let font: UIFont = UIFont(name: "SourceCodePro-Regular", size: label.font.pointSize)!

        let rect = string.boundingRectWithSize(CGSizeMake(label.frame.width, CGFloat(MAXFLOAT)), options: NSStringDrawingOptions.UsesLineFragmentOrigin, attributes: [font : NSFontAttributeName], context: nil)

        return Int(ceil(rect.size.height/font.lineHeight))

    }

    func numberOfLinesForString(string: String, size: CGSize, font: UIFont) -> Int {
        let textStorage = NSTextStorage(string: string, attributes: [NSFontAttributeName: font])

        let textContainer = NSTextContainer(size: size)
        textContainer.lineBreakMode = .ByWordWrapping
        textContainer.maximumNumberOfLines = 0
        textContainer.lineFragmentPadding = 0

        let layoutManager = NSLayoutManager()
        layoutManager.textStorage = textStorage
        layoutManager.addTextContainer(textContainer)

        var numberOfLines = 0
        var index = 0
        var lineRange : NSRange = NSMakeRange(0, 0)
        for (; index < layoutManager.numberOfGlyphs; numberOfLines++) {
            layoutManager.lineFragmentRectForGlyphAtIndex(index, effectiveRange: &lineRange)
            index = NSMaxRange(lineRange)
        }

        return numberOfLines
    }

因为它是一个自动调整大小的单元,我不能执行此操作吗?

编辑-这里是我正在使用的文本数组:

var randomSizedTexts = [
        "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\nUt enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.",
        "Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur?",
        "Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem",
        ", sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora",
        "At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident",
        "Et harum quidem rerum facilis est et expedita distinctio",
        "Mauris id efficitur sapien. Nunc lobortis nisi ut ultricies scelerisque. Curabitur accumsan sit amet lacus in finibus. Aliquam dolor ante, rhoncus sit amet fermentum et, semper sit amet nisi. Proin pretium velit ut quam mollis fringilla. Nullam neque risus, vestibulum eget tortor sit amet, suscipit ultricies metus. In tortor ipsum, feugiat lacinia leo id, pulvinar lacinia velit. Suspendisse sit amet porta tellus, et scelerisque odio. Nam convallis sodales congue. Proin vel quam id arcu nisi non.",

    ]
禁令

尝试使用NSAttributedString

func lineCountForLabel(label: UILabel) -> Int {

    let font: UIFont = label.font

    let attribtedString = label.attributedText.mutableCopy() as! NSMutableAttributedString
    let paragraphStyle = NSMutableParagraphStyle()
    paragraphStyle.lineBreakMode = label.lineBreakMode
    attribtedString.addAttribute(NSParagraphStyleAttributeName, value: paragraphStyle, range: NSRange(location: 0, length: attribtedString.length))

    let rect = attribtedString.boundingRectWithSize(CGSizeMake(label.frame.width, CGFloat(MAXFLOAT)),
        options: .UsesLineFragmentOrigin | .UsesFontLeading,
        context: nil)

    return Int(ceil(rect.size.height/font.lineHeight))
}

更新:

您可以将字典的类型写为[Key:Value]的简写形式,因此您的这一行是不正确的:

let rect = string.boundingRectWithSize(xx, xx, xx, attributes: [font : NSFontAttributeName], context: nil)

更改:

[font : NSFontAttributeName]

至:

[NSFontAttributeName : font]

UPDATE(问题更新后)

您应该像这样在您的dataSource中存储一个行号:

class MyCell: UITableViewCell {

    @IBOutlet var contentLabel: UILabel!
    @IBOutlet private var numberLabel: UILabel!
}

class MasterViewController: UITableViewController {

    var objects = [AnyObject]()

    override func viewDidLoad() {
        super.viewDidLoad()

        let addButton = UIBarButtonItem(barButtonSystemItem: .Add, target: self, action: "insertNewObject:")
        self.navigationItem.rightBarButtonItem = addButton

        self.tableView.estimatedRowHeight = 44
        self.tableView.rowHeight = UITableViewAutomaticDimension

        self.insertNewObject(self)
        self.insertNewObject(self)
        self.insertNewObject(self)
        self.insertNewObject(self)
        self.insertNewObject(self)
        self.insertNewObject(self)
        self.insertNewObject(self)
        self.insertNewObject(self)
        self.insertNewObject(self)
        self.insertNewObject(self)
    }

    func insertNewObject(sender: AnyObject) {
        var count = Int(arc4random_uniform(20)) + 1

        var string = ""
        while (count-- > 0) {
            string += "This is a test."
        }
        objects.insert(["content" : string, "lineNumber" : 0], atIndex: 0)
    }

    // MARK: - Table View

    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return objects.count
    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! MyCell

        var object = objects[indexPath.row] as! [String : AnyObject]

        var startLineNumber = 0
        if indexPath.row > 0 {
            var pObject = objects[indexPath.row - 1] as! [String : AnyObject]
            startLineNumber = pObject["lineNumber"] as! Int
        }

        cell.contentView.setNeedsLayout()
        cell.contentView.layoutIfNeeded()

        cell.contentLabel.text = object["content"] as? String
        let lineNumber = lineCountForLabel(cell.contentLabel)  + startLineNumber
        cell.numberLabel.text = "\(lineNumber)"

        object["lineNumber"] = lineNumber
        objects[indexPath.row] = object

        return cell
    }

    func lineCountForLabel(label: UILabel) -> Int {

        let font: UIFont = label.font

        let attribtedString = label.attributedText.mutableCopy() as! NSMutableAttributedString
        let paragraphStyle = NSMutableParagraphStyle()
        paragraphStyle.lineBreakMode = label.lineBreakMode
        attribtedString.addAttribute(NSParagraphStyleAttributeName, value: paragraphStyle, range: NSRange(location: 0, length: attribtedString.length))

        let rect = attribtedString.boundingRectWithSize(CGSizeMake(label.frame.width, CGFloat(MAXFLOAT)),
            options: .UsesLineFragmentOrigin | .UsesFontLeading,
            context: nil)

        return Int(ceil(rect.size.height/font.lineHeight))
    }

}

更新

您的演示中有一些问题。

更改

lastNumUsed = 1

lastNumUsed = 0

并改变

for index in lastNumUsed+1...lastNumUsed+numLines

for index in lastNumUsed+1...lastNumUsed+numLines-1

最后,问题的关键在于gameInfo的大小是否正确。cellForRow执行时,它的superview可能为零,因此单元格的大小和gameInfo是不正确的。相反,您应该willDisplayCell像这样计算行数

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    var cell: LineNumberSubtitleCell! = tableView.dequeueReusableCellWithIdentifier("GameCell", forIndexPath: indexPath) as! LineNumberSubtitleCell

    if cell == nil {
        cell = LineNumberSubtitleCell(style: UITableViewCellStyle.Default, reuseIdentifier: "GameCell")
    }

    cell.gameInfo.text = randomSizedTexts[indexPath.row]

    return cell
}

override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
    let cell = cell as! LineNumberSubtitleCell

    cell.contentView.setNeedsLayout()
    cell.contentView.layoutIfNeeded()

    let numLines = getLinesArrayOfStringInLabel(cell.gameInfo)
    cell.lineNumbers.text = "\(lastNumUsed)"

    if !(lineNumbersList.count > indexPath.row) {

        for index in lastNumUsed+1...lastNumUsed+numLines-1 {

            cell.lineNumbers.text = cell.lineNumbers.text?.stringByAppendingString("\n\(index)")

            if index == lastNumUsed+numLines-1 {

                lastNumUsed = index+1
                lineNumbersList.addObject(cell.lineNumbers.text!)
            }
        }
    } else {
        cell.lineNumbers.text = lineNumbersList.objectAtIndex(indexPath.row) as? String
    }
}

调用该setNeedsLayout方法将强制您的视图更新其布局。调用该layoutIfNeeded方法将强制立即运行布局系统。因此,gameInfo应重新计算的大小以更正。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何在自定义表格视图单元格中创建自定义视图?

如何在表格视图单元格中隐藏自定义类标签?

在自定义表格视图单元格中本地化按钮和标签[swift]

无法在UI表格视图自定义单元格中创建分隔符插入

Swift中的自定义表格视图单元格,没有Storyboard

自定义表格视图单元格在xcode 6中快速

故事板中的自定义表格视图单元格布局似乎无效

创建取决于UILabel高度的自定义表格视图单元格

表格视图单元格之间的自定义视图

自定义表格视图单元格图像失真

使用UIView的自定义表格视图单元格

自定义视图单元格中的单元格间距

TableView 自定义单元格中的自定义 UIView 在表格加载时“跳跃”

分隔符未正确显示为ios中的自定义表格视图单元格

Swift:在表格视图单元格中创建UILabel

Swift TableView多个自定义单元格,增加单元格中的行数导致崩溃

自定义UITableView单元格中的UILabel不会随着核心数据的更改而更新

在自定义 tableView 单元格中:UILabel 的背景超出了文本长度(以编程方式)

使用自定义单元格在UITableView中展开UILabel时,Swift崩溃

如何从自定义单元格显示 UILabel 保存在 UITableView 中的更改

在自定义渲染中单击单元格时,bootstrap vue 获取行数据

使用其他单元格中的值在Google表格中创建自定义URL

从 html 表格中的多个单元格中减去自定义金额

XCode的表视图单元格中的自定义卡视图设计

无法在 iOSSwift 中的自定义集合视图单元格中圆角标签

所有单元格子视图都位于哪个子视图?(在自定义单元格类中)

在由笔尖制成的自定义表格单元格中单击时更改图像

viewDidLoad中的变量未填充自定义表格单元格

在 tableView(:didSelectRowAt) 中设置自定义表格单元格 UILabels 的值