首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在UILabel末尾添加"...Read More“

在UILabel末尾添加"...Read More“
EN

Stack Overflow用户
提问于 2015-08-31 18:33:22
回答 9查看 50.4K关注 0票数 22

我有一个UILabel,在某些情况下,文本比UILabel本身还要长,所以我将文本看作"bla bla bla...",我想在UILabel的末尾添加一个...Read More按钮文本。

我读过一些帖子,但他们提供的解决方案对我来说并不好,例如:计算有多少个字符将进入UILabel,但我使用的字体每个字符都有不同的宽度。

我怎样才能做到这一点?

提前感谢!

EN

回答 9

Stack Overflow用户

发布于 2019-03-22 11:22:27

这适用于Swift 5

这里是@ramchandran答案的一个更安全的版本,因为您不知道用户将输入多少个字符。

在他的回答中,如果用户输入的字符串长度小于您决定用于... Readmore的任何文本的长度,那么它将崩溃。例如,这就是你使用它的方式

代码语言:javascript
复制
if yourLabel.text!.count > 1 {

   let readmoreFont = UIFont(name: "Helvetica-Oblique", size: 11.0)
    let readmoreFontColor = UIColor.blue
    DispatchQueue.main.async {
        self.yourLabel.addTrailing(with: "... ", moreText: "Readmore", moreTextFont: readmoreFont!, moreTextColor: readmoreFontColor)
    }
}

在上面的例子中,... Readmore的输出总共是12个字符。如果用户输入的字符串是yourLabel.text = "12345678",那么字符串的文本将只有8个字符。它会崩溃,因为在下面一行中使用((trimmedString?.count ?? 0) - readMoreLength)的范围将产生负结果:

代码语言:javascript
复制
// “12345678” minus “... Readmore” = negative four (8 - 12 = -4)
let trimmedForReadMore: String = (trimmedString! as NSString).replacingCharacters(in: NSRange(location: ((trimmedString?.count ?? 0) - readMoreLength), length: readMoreLength), with: "") + trailingText

我添加了一个安全检查,以确保如果输入的字符串少于或等于您决定用作... Readmore的任何字符串的字符数,它将返回,并且将导致崩溃的行永远不会到达:

代码语言:javascript
复制
// trimmedString is the string the user entered
guard let safeTrimmedString = trimmedString else { return }
if safeTrimmedString.count <= readMoreLength { return }

它位于addTrailing函数的中心

代码语言:javascript
复制
extension UILabel{    
    
    func addTrailing(with trailingText: String, moreText: String, moreTextFont: UIFont, moreTextColor: UIColor) {
        
        let readMoreText: String = trailingText + moreText
        
        if self.visibleTextLength == 0 { return }
        
        let lengthForVisibleString: Int = self.visibleTextLength
        
        if let myText = self.text {
            
            let mutableString: String = myText
            
            let trimmedString: String? = (mutableString as NSString).replacingCharacters(in: NSRange(location: lengthForVisibleString, length: myText.count - lengthForVisibleString), with: "")
            
            let readMoreLength: Int = (readMoreText.count)
            
            guard let safeTrimmedString = trimmedString else { return }
            
            if safeTrimmedString.count <= readMoreLength { return }
            
            print("this number \(safeTrimmedString.count) should never be less\n")
            print("then this number \(readMoreLength)")
            
            // "safeTrimmedString.count - readMoreLength" should never be less then the readMoreLength because it'll be a negative value and will crash
            let trimmedForReadMore: String = (safeTrimmedString as NSString).replacingCharacters(in: NSRange(location: safeTrimmedString.count - readMoreLength, length: readMoreLength), with: "") + trailingText
            
            let answerAttributed = NSMutableAttributedString(string: trimmedForReadMore, attributes: [NSAttributedString.Key.font: self.font])
            let readMoreAttributed = NSMutableAttributedString(string: moreText, attributes: [NSAttributedString.Key.font: moreTextFont, NSAttributedString.Key.foregroundColor: moreTextColor])
            answerAttributed.append(readMoreAttributed)
            self.attributedText = answerAttributed
        }
    }
    
    var visibleTextLength: Int {
        
        let font: UIFont = self.font
        let mode: NSLineBreakMode = self.lineBreakMode
        let labelWidth: CGFloat = self.frame.size.width
        let labelHeight: CGFloat = self.frame.size.height
        let sizeConstraint = CGSize(width: labelWidth, height: CGFloat.greatestFiniteMagnitude)
        
        if let myText = self.text {
            
            let attributes: [AnyHashable: Any] = [NSAttributedString.Key.font: font]
            let attributedText = NSAttributedString(string: myText, attributes: attributes as? [NSAttributedString.Key : Any])
            let boundingRect: CGRect = attributedText.boundingRect(with: sizeConstraint, options: .usesLineFragmentOrigin, context: nil)
            
            if boundingRect.size.height > labelHeight {
                var index: Int = 0
                var prev: Int = 0
                let characterSet = CharacterSet.whitespacesAndNewlines
                repeat {
                    prev = index
                    if mode == NSLineBreakMode.byCharWrapping {
                        index += 1
                    } else {
                        index = (myText as NSString).rangeOfCharacter(from: characterSet, options: [], range: NSRange(location: index + 1, length: myText.count - index - 1)).location
                    }
                } while index != NSNotFound && index < myText.count && (myText as NSString).substring(to: index).boundingRect(with: sizeConstraint, options: .usesLineFragmentOrigin, attributes: attributes as? [NSAttributedString.Key : Any], context: nil).size.height <= labelHeight
                return prev
            }
        }
        
        if self.text == nil {
            return 0
        } else {
            return self.text!.count
        }
    }
}
票数 8
EN

Stack Overflow用户

发布于 2019-09-22 10:11:03

代码语言:javascript
复制
class DynamicLabel: UILabel{

    var fullText: String?
    var truncatedLength = 100
    var isTruncated = true

    func collapse(){
        let index = fullText!.index(fullText!.startIndex, offsetBy: truncatedLength)
        self.text = fullText![...index].description + "... More"
        isTruncated = true
    }

    func expand(){
        self.text = fullText
        isTruncated = false
    }

}

这只是一个简单的技巧来完成所有这些杂乱的实现。想法很简单,我们不设置折叠或展开行,只需将标签设置为0。然后将原始文本存储在fullText变量中。现在,如果我们想要显示折叠格式,那么只需获取substring并添加自定义省略号即可。

注意:这不包括点击事件处理程序,你可以自己在控制器上添加它。

票数 3
EN

Stack Overflow用户

发布于 2015-08-31 18:39:59

使用方法- boundingRectWithSize:options:attributes:context:并将您的字体作为NSFontAttributeName键传递给NSAttributedString将为您提供所需的正确rect。

因此,您需要检查它是否大于标签边界减去偏移量。只有在是的时候,你才需要裁剪你的文本并在最后显示Read More

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32309247

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档