NSAttributedString: left and right alignment

I'm trying to set up a text view to show lines of text, along with line numbers on the right margin. The string for the text view would look something like this:


"Text of first line" + "Line 1" + "\n" + "Text of second line" + "Line 2" + "\n"


I want the end result to look something like this:


Into my heart an air that kills, 1

From yon far country blows: 2

What are those blue remembered hills, 3

What spires, what farms are those? 4


(Sorry about the crooked right column: it looked fine in the message editor. The numbers should all be in a straight column, aligned to the right margin of the text view.)


Is it possible to use an NSAttributedString to do this? I've tried several different ways of constructing such a string, but no luck so far. I'm beginning to think this is the wrong approach entirely. What is the best way to get the kind of layout that I want?

Accepted Reply

hi Albinus,


using some code i was looking at yesterday (you may recognize it), you can do this with tabStops. i did exactly what you asked, but placing the text in a 4-line label as white text on a blue background ("testLabel" was set up as an @IBOutlet in a storyboard and this code is executed on viewWillAppear())


testLabel.backgroundColor = UIColor.blue
testLabel.numberOfLines = 4

let myStyle = NSMutableParagraphStyle()
let labelWidth = testLabel.frame.size.width
myStyle.tabStops = [NSTextTab(textAlignment: .left, location: 0.0, options: [:]),
  NSTextTab(textAlignment: .right, location: labelWidth, options: [:])]


let tabChar = "\t"
let returnChar = "\r"

let content = "Into my heart an air that kills" + tabChar + "1" + returnChar +
  "From yon far country blows:" + tabChar + "2" + returnChar +
  "What are those blue remembered hills" + tabChar + "3" + returnChar +
  "What spires, what farms are those?" + tabChar + "4" + returnChar


let attributes: [NSAttributedString.Key: Any] = [.foregroundColor: UIColor.white]
let attrString = NSMutableAttributedString(string: content, attributes: attributes)
attrString.addAttribute(.paragraphStyle, value: myStyle, range: NSRange(location: 0, length: content.count-1))
testLabel.attributedText = attrString



the results should be transferrable to a UITextView()


hope that helps,

DMG

Replies

hi Albinus,


using some code i was looking at yesterday (you may recognize it), you can do this with tabStops. i did exactly what you asked, but placing the text in a 4-line label as white text on a blue background ("testLabel" was set up as an @IBOutlet in a storyboard and this code is executed on viewWillAppear())


testLabel.backgroundColor = UIColor.blue
testLabel.numberOfLines = 4

let myStyle = NSMutableParagraphStyle()
let labelWidth = testLabel.frame.size.width
myStyle.tabStops = [NSTextTab(textAlignment: .left, location: 0.0, options: [:]),
  NSTextTab(textAlignment: .right, location: labelWidth, options: [:])]


let tabChar = "\t"
let returnChar = "\r"

let content = "Into my heart an air that kills" + tabChar + "1" + returnChar +
  "From yon far country blows:" + tabChar + "2" + returnChar +
  "What are those blue remembered hills" + tabChar + "3" + returnChar +
  "What spires, what farms are those?" + tabChar + "4" + returnChar


let attributes: [NSAttributedString.Key: Any] = [.foregroundColor: UIColor.white]
let attrString = NSMutableAttributedString(string: content, attributes: attributes)
attrString.addAttribute(.paragraphStyle, value: myStyle, range: NSRange(location: 0, length: content.count-1))
testLabel.attributedText = attrString



the results should be transferrable to a UITextView()


hope that helps,

DMG

For such precise presentation, I would use 2 textView and sync when scroll (if ever you scroll).

It is not totally trivial to do, but result is clean.


PS: it would be so much simpler to write numbers on the left (kidding 😁).

I didn't realize that one could set tab stops in a paragraph style. That is exactly what I needed to know! It should solve all my problems. Many thanks.

I did try putting them on the left, but when they get too long (up to 4 digits in the Iliad, for example), they push the text out of alignment. But now that I'm aware of how to set tab stops in paragraph styles, that problem can be solved too.