I have a UILabel
with RTL Arabic text inside. Everything appears correctly as long as I don't change the lineBreakMode
. I need it to clip instead of byTruncatingTail
in order to avoid showing the ellipses character as I'm trying to show a gradient mask on the left edge.
I've tried changing contentMode
, alignment
etc but nothing helps. The right side of the label seems to start text from the middle somewhere, instead of from the start (i.e. the right most character in the text).
This is what I see with lineBreakMode = .byClipping
And this is what I see when I remove the lineBreakMode
Here's the code
let arabicLabel = UILabel(frame: .zero)
arabicLabel.semanticContentAttribute = .forceRightToLeft
arabicLabel.numberOfLines = 1
//arabicLabel.lineBreakMode = .byClipping
arabicLabel.text = "عِنْدَمَا1 عِنْدَمَا2 عِنْدَمَا3 عِنْدَمَا4 عِنْدَمَا5 عِنْدَمَا6 قَدِمْتُ عَلَى (صَاحِبِي) عِنْدَمَا7 عِنْدَمَا8 عِنْدَمَا9 عِنْدَمَا10 عِنْدَمَا عِنْدَمَا قَدِمْتُ عَلَى (صَاحِبِي)"
arabicLabel.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(arabicLabel)
After wasting enough time on this, I ended doing it the ugly way, by overriding drawText
and adding an arbitrary amount of padding to effectively hide the ellipses character and handling it for both RTL and LTR. I could have based this on the semanticContentAttributes
instead, but in my case the label will only ever be right aligned when it contains RTL text. I've also had to override text
to automatically detect the dominant language set, and alter the alignment automatically.
public override func drawText(in rect: CGRect) {
let extraWidth = fadeLength + 50
var newRect = rect
if self.textAlignment == .right {
newRect.origin.x -= extraWidth
newRect.size.width += extraWidth
} else {
newRect.size.width += extraWidth
}
super.drawText(in: newRect)
}