I need to add "... Read more" to the end of UITextView. I use this solution Add "...Read More" to the end of UILabel. I tried to use it with UILabel - it works perfectly. But in UITextView "... Read more" position isn't stable. I think the problem is in textViewWidth
and textViewHeight
. When I change their values to -10 it works better but not really. How can I solve it?
My code:
var visibleTextLength: Int {
guard let text = text else { return 0 }
let mode: NSLineBreakMode = textContainer.lineBreakMode
let textViewWidth: CGFloat = frame.size.width //adding - 10 helps a little
let textViewHeight: CGFloat = frame.size.height //adding - 10 helps a little
let sizeConstraint = CGSize(width: textViewWidth, height: CGFloat.greatestFiniteMagnitude)
let attributes: [AnyHashable: Any] = [NSAttributedString.Key.font: font!]
let attributedText = NSAttributedString(string: text, attributes: attributes as? [NSAttributedString.Key: Any])
let boundingRect: CGRect = attributedText.boundingRect(with: sizeConstraint, options: .usesLineFragmentOrigin, context: nil)
if boundingRect.size.height > textViewHeight {
var index = 0
var prev = 0
let characterSet = CharacterSet.alphanumerics
repeat {
prev = index
if mode == NSLineBreakMode.byCharWrapping {
index += 1
} else {
index = (text as NSString).rangeOfCharacter(from: characterSet, options: [], range: NSRange(location: index + 1, length: text.utf16.count - index - 1)).location
}
} while index != NSNotFound && index < text.utf16.count && (text as NSString).substring(to: index).boundingRect(with: sizeConstraint, options: .usesLineFragmentOrigin, attributes: attributes as? [NSAttributedString.Key: Any], context: nil).size.height <= textViewHeight
return prev
}
return text.utf16.count
}
func addTrailing(with trailingText: String, moreText: String, moreTextFont: UIFont?) {
guard self.visibleTextLength > 0 else { return }
let readMoreText: String = trailingText + moreText
let lengthForVisibleString: Int = self.visibleTextLength
if let text = self.text {
let mutableString: String = text
let trimmedString: String? = (mutableString as NSString).replacingCharacters(in: NSRange(location: lengthForVisibleString, length: text.utf16.count - lengthForVisibleString), with: "")
let readMoreLength: Int = (readMoreText.utf16.count)
guard let safeTrimmedString = trimmedString, safeTrimmedString.utf16.count >= readMoreLength else { return }
let trimmedForReadMore: String = (safeTrimmedString as NSString).replacingCharacters(in: NSRange(location: safeTrimmedString.utf16.count - readMoreLength, length: readMoreLength), with: "") + trailingText
let attributedMoreText = NSMutableAttributedString(string: trimmedForReadMore,
attributes: [NSAttributedString.Key.font: font!])
if let moreTextFont = moreTextFont {
let readMoreAttributed = NSMutableAttributedString(string: moreText, attributes: [NSAttributedString.Key.font: moreTextFont])
attributedMoreText.append(readMoreAttributed)
}
self.attributedText = attributedMoreText
}
}
With - 10 in textViewWidth
and textViewHeight