-5

I want to get first two lines text from UIlabel.I have searched a lot but not find any solution.Please tell me how to get first two lines text.

Gaurav Gupta
  • 593
  • 2
  • 10
  • 31
  • please add your sample text and what you are using. – Yatendra Feb 16 '18 at 09:24
  • Like the example in one paragraph set text in UILabel.Then I want to get first two lines from the paragraph. – Gaurav Gupta Feb 16 '18 at 09:27
  • 1
    Can I ask why would you would need to do this? you are basically cutting a string based on the size of a UI element that will be different sizes on different devices. what are you trying to achieve? – Scriptable Feb 16 '18 at 09:28
  • I am basically trying to append "View more..." text in UIlabel when text is greater than 2 lines.So please tell me how to achieve this. – Gaurav Gupta Feb 16 '18 at 09:30

3 Answers3

1

Use this extension check if your label's number of line granter then 2 or whatever you target then apply this:

extension UILabel {

    func addTrailing(with trailingText: String, moreText: String, moreTextFont: UIFont, moreTextColor: UIColor) {
        let readMoreText: String = trailingText + moreText

        let lengthForVisibleString: Int = self.vissibleTextLength()
        let mutableString: String = self.text!
        let trimmedString: String? = (mutableString as NSString).replacingCharacters(in: NSRange(location: lengthForVisibleString, length: ((self.text?.characters.count)! - lengthForVisibleString)), with: "")
        let readMoreLength: Int = (readMoreText.characters.count)
        let trimmedForReadMore: String = (trimmedString! as NSString).replacingCharacters(in: NSRange(location: ((trimmedString?.characters.count ?? 0) - readMoreLength), length: readMoreLength), with: "") + trailingText
        let answerAttributed = NSMutableAttributedString(string: trimmedForReadMore, attributes: [NSFontAttributeName: self.font])
        let readMoreAttributed = NSMutableAttributedString(string: moreText, attributes: [NSFontAttributeName: moreTextFont, NSForegroundColorAttributeName: moreTextColor])
        answerAttributed.append(readMoreAttributed)
        self.attributedText = answerAttributed
    }

    func vissibleTextLength() -> 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)

        let attributes: [AnyHashable: Any] = [NSFontAttributeName: font]
        let attributedText = NSAttributedString(string: self.text!, attributes: attributes as? [String : 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 = (self.text! as NSString).rangeOfCharacter(from: characterSet, options: [], range: NSRange(location: index + 1, length: self.text!.characters.count - index - 1)).location
                }
            } while index != NSNotFound && index < self.text!.characters.count && (self.text! as NSString).substring(to: index).boundingRect(with: sizeConstraint, options: .usesLineFragmentOrigin, attributes: attributes as? [String : Any], context: nil).size.height <= labelHeight
            return prev
        }
        return self.text!.characters.count
    }
}

Count Label's number of line:

func countLabelLines(label: UILabel) -> Int {
        // Call self.layoutIfNeeded() if your view uses auto layout
        self.view.layoutIfNeeded()
        let myText = label.text! as NSString

        let rect = CGSize(width: label.bounds.width, height: CGFloat.greatestFiniteMagnitude)
        let labelSize = myText.boundingRect(with: rect, options: .usesLineFragmentOrigin, attributes: [NSFontAttributeName: label.font], context: nil)

        return Int(ceil(CGFloat(labelSize.height) / label.font.lineHeight))
    }

Example:

if self.countLabelLines(label: lblmedicationDetailText) >= numberOflines{

            let readmoreFont = UIFont(name: "Montserrat-Regular", size: 15.0)
            let readmoreFontColor = UIColor.init(red: 1.0/255.0, green: 100.0/255.0, blue: 157.0/255.0, alpha: 1.0)
            DispatchQueue.main.async {
                self.lblmedicationDetailText.addTrailing(with: "... ", moreText: "Read More", moreTextFont: readmoreFont!, moreTextColor: readmoreFontColor)
            }
        }
Som Parkash
  • 234
  • 3
  • 9
  • 1
    That looks like a verbatim copy from https://stackoverflow.com/a/44064496. Have a look at https://stackoverflow.com/help/referencing about how to reference code written by others, and plagiarism. – Martin R Feb 16 '18 at 09:52
  • __NSCFString replaceCharactersInRange:withString:]: Range or index out of bounds. error occur when the string is long without space. – Gaurav Gupta Feb 16 '18 at 10:31
0
let numOfLine = self.numberOfLinesInLabel(self.testingLabel.text!, labelWidth: self.testingLabel.frame.width, labelHeight: self.testingLabel.frame.height, font: self.testingLabel.font)

self.getNumberOfLineDict.setValue(numOfLine, forKey: String(i))


let Lines : Int = getNumberOfLineDict.valueForKey(String(indexPath.row)) as! Int // I did it in tableview. So I used indexPath.row

if Lines > 2
{
   ReadmoreBtn.isHidden = false
}
else
{
   ReadmoreBtn.isHidden = true
}

To get the number of lines in a text

 func numberOfLinesInLabel(yourString: String, labelWidth: CGFloat, labelHeight: CGFloat, font: UIFont) -> Int {

        let paragraphStyle = NSMutableParagraphStyle()
        paragraphStyle.minimumLineHeight = labelHeight
        paragraphStyle.maximumLineHeight = labelHeight
        paragraphStyle.lineBreakMode = .ByWordWrapping

        let attributes: [String: AnyObject] = [NSFontAttributeName: font, NSParagraphStyleAttributeName: paragraphStyle]

        let constrain = CGSizeMake(labelWidth, CGFloat(Float.infinity))

        let size = yourString.sizeWithAttributes(attributes)
        let stringWidth = size.width

        let numberOfLines = ceil(Double(stringWidth/constrain.width))
        return Int(numberOfLines)
  }
Catherine
  • 654
  • 5
  • 15
0

My advice is doing something on UI only. You can set a UIView(such as it has gradual clear to white view and has a label "View more...") to cover the original label except first two lines. You can get the first two lines height by label.font.lineHeight * 2.

ribilynn
  • 460
  • 5
  • 21