0

I have to show 3 text on one UITextView , This can be multiline or single line,

  1. in Multiline there is no issue .

enter image description here

  1. but when there is single line enabled then text is truncated from end because i'm using

    .lineBreakMode = NSLineBreakMode.byTruncatingTail

enter image description here

3. But my desired work it to truncate the middle part of Text (Message)

enter image description here

what i have tried till now !

 @IBAction func btnSwitchAction(_ sender: UISwitch) {
        self.isMultilineEnabled = sender.isOn
    }
    
    func setup() {
        textView.isScrollEnabled = false
        textView.isEditable = false
        reloadTextView()
    }
    

    func reloadTextView() {
        let padding = textView.textContainer.lineFragmentPadding
        textView.textContainerInset = UIEdgeInsets(top: 0, left: -padding, bottom: 0, right: -padding)
        textView.textContainer.maximumNumberOfLines =  isMultilineEnabled ? 0 : 1;
        textView.textContainer.lineBreakMode = isMultilineEnabled ? NSLineBreakMode.byWordWrapping : NSLineBreakMode.byTruncatingTail
        textView.attributedText = getAttributedString(title: "Des", messageStr: "In publishing and graphic design, Lorem ipsum is a placeholder text commonly used to demonstrate the visual form of a document or a typeface without relying on meaningful content. Lorem ipsum may be used as a placeholder", actionButton: "Share")
        textView.layoutIfNeeded()
        textView.translatesAutoresizingMaskIntoConstraints = true
        textView.sizeToFit()
    }
    

    private func getAttributedString(title: String, messageStr: String, actionButton: String = "") -> NSAttributedString {
        let defaultFont = UIFont.systemFont(ofSize: fontSize)
        let boldFont = UIFont.systemFont(ofSize: fontSize, weight: .bold)
       
        let finalAttributedString = NSMutableAttributedString.init(string: "")
        
        let firstText = "\(title):"
        let regulerAttributedText = NSMutableAttributedString(string: firstText,
                                                              attributes: [NSAttributedString.Key.font : boldFont])
        finalAttributedString.append(regulerAttributedText)
    
        let secondAttributedText = NSMutableAttributedString(string: messageStr,
                                                              attributes: [NSAttributedString.Key.font : defaultFont])
        finalAttributedString.append(secondAttributedText)
        finalAttributedString.addAttributes([NSAttributedString.Key.foregroundColor : UIColor.black.cgColor], range: NSMakeRange(0, finalAttributedString.string.count))
                
        if !actionButton.isEmpty {
            let actionFont = UIFont.systemFont(ofSize: fontSize, weight: .medium)
            let actionTextAttribute = NSMutableAttributedString(string: " \(actionButton)")
            actionTextAttribute.addAttributes([NSAttributedString.Key.foregroundColor : UIColor.orange.cgColor,
                                                NSAttributedString.Key.font : defaultFont],
                                              range: NSMakeRange(0, actionButton.count + 1))
            finalAttributedString.append(actionTextAttribute)
        }
        return finalAttributedString
    }

If i can get the number of text which can fit in one line then i can archive the desired result by trimming middle text . i wrote extension but its not giving correct number of texts.

extension NSLayoutManager {
    
    /**
     Returns characters range that completely fits into container.
     */
    public func characterRangeThatFits(textContainer container: NSTextContainer) -> NSRange {
        var rangeThatFits = self.glyphRange(for: container)
        rangeThatFits = self.characterRange(forGlyphRange: rangeThatFits, actualGlyphRange: nil)
        return rangeThatFits
    }
 }
Dhiru
  • 3,040
  • 3
  • 25
  • 69

1 Answers1

0

Try this, declare your text view string:

let myString = "Monthly price reflects net monthly payment, after application of AT&T trade‑in credit applied over 36 months with purchase of an iPhone 14 Pro, iPhone 14 Pro Max, iPhone 14, or iPhone 14 Plus and trade‑in of eligible smartphone. Receive credit with purchase of an iPhone 14 Pro or iPhone 14 Pro Max of either $1000, $700, or $350 (based upon the model and condition of your trade‑in smartphone). Receive credit with purchase of an iPhone 14 or iPhone 14 Plus of either $700 or $350 (based upon the model and condition of your trade‑in smartphone)."

after that in viewDidLoad:

let words = myString.components(separatedBy: " ")

    if words.count > 1 {
        let halfLength = words.count / 2
        let firstHalf = words[0..<halfLength].joined(separator: " ")
        let secondHalf = words[halfLength..<words.count].joined(separator: " ")
        print("First half:", firstHalf)
        print("Second half half:", secondHalf)
        yourTextView.text = firstHalf // or secondHalf
    } else {
        print("Input string contains only one word")
    }

Output First half:

First half: Monthly price reflects net monthly payment, after application of AT&T trade‑in credit applied over 36 months with purchase of an iPhone 14 Pro, iPhone 14 Pro Max, iPhone 14, or iPhone 14 Plus and

Output Second half:

Second half half: trade‑in of eligible smartphone. Receive credit with purchase of an iPhone 14 Pro or iPhone 14 Pro Max of either $1000, $700, or $350 (based upon the model and condition of your trade‑in smartphone).
Fabio
  • 5,432
  • 4
  • 22
  • 24