surToTheW
surToTheW

Reputation: 832

Bulleted list in Swift - iOS

I need to add bulleted text to textView in iOS app. I am looking at this link and this one and following their ideas. This is my code:

let paragraph = NSMutableParagraphStyle()
paragraph.firstLineHeadIndent = 15
paragraph.headIndent = 15

attributes = [
    NSAttributedStringKey.paragraphStyle: paragraph
]

attributedString = NSAttributedString(string: "\u{2022} Some text some text some text some text some text some text", attributes: attributes)
finalText.append(attributedString)

What I need is to get the text indented with the start of the text above. Like it is in the picture:

enter image description here

What I get is the text indented with the starting point of the bullet.

enter image description here

Upvotes: 7

Views: 14774

Answers (6)

Mohsen Fard
Mohsen Fard

Reputation: 598

I had the same problem, and I finally realized that Label didn't support it. If you want to use bullet-list in the same rows you should use text view

Upvotes: 0

hbk
hbk

Reputation: 11184

Simple solution:

extension Sequence where Self.Element == String {

  func toBulletList(_ bulletIndicator: String = "•",
                    itemSeparator: String = "\n",
                    spaceCount: Int = 2) -> String {
    let bullet = bulletIndicator + String(repeating: " ", count: spaceCount)
    let list = self
      .map { bullet + $0 }
      .reduce("", { $0 + ($0.isEmpty ? $0 : itemSeparator) + $1 })
    return list
  }
}

usage:

let items: [String] = [
"one",
"two",
"three"
]

let list = items.toBulletList()
po list -> 
    •  one
    •  two
    •  three

Upvotes: 3

Matt Bearson
Matt Bearson

Reputation: 1033

To have the headIndent resize with dynamic fonts I'm using this:

private func updateUI() {
    let bullet: NSString = "• "
    var attributes = [NSAttributedString.Key: Any]()
    let paragraph = NSMutableParagraphStyle()
    leStackView.subviews.compactMap({ $0 as? UILabel }).forEach {
        attributes[.font] = $0.font
        paragraph.headIndent = bullet.size(withAttributes: attributes).width
        attributes[.paragraphStyle] = paragraph
        let text = $0.text ?? ""
        $0.attributedText = NSAttributedString(string: text, attributes: attributes)
    }
}

The labels for each bullet point are set up in the storyboard with plain text (including the bullet) and dynamic fonts.

I really appreciate the contributions to this thread plus https://bendodson.com/weblog/2018/08/09/bulleted-lists-with-uilabel/

Upvotes: 6

Jack
Jack

Reputation: 14359

I faced same problem with textView i used custom indent & it working fine-

 @IBOutlet  var bulletTextView: UITextView!

 override func viewDidLoad() {
        let bullet1 = "This is a small string,This is a small string,This is a small string,This is a small string,This is a small string,This is a small string,This is a small string"
        let bullet2 = "This is more of medium string with a few more words etc."
        let bullet3 = "Well this is certainly a longer string, with many more words than either of the previuos two strings"
        strings = [bullet1, bullet2, bullet3]
        let fullAttributedString = NSMutableAttributedString()
        for string: String in strings {
            let attributesDictionary:[NSAttributedStringKey:Any] = [NSAttributedStringKey.font : bulletTextView.font,NSAttributedStringKey.foregroundColor : UIColor.red]
            let bulletPoint: String = "\u{2022}"
            //let formattedString: String = "\(bulletPoint) \(string)\n"
            let attributedString = NSMutableAttributedString(string: bulletPoint, attributes: attributesDictionary)
            attributedString.append(NSAttributedString(string: " \(string) \n"))
            let indent:CGFloat = 15
            let paragraphStyle = createParagraphAttribute(tabStopLocation: indent, defaultTabInterval: indent, firstLineHeadIndent: indent - 10, headIndent: indent)
            attributedString.addAttributes([NSAttributedStringKey.paragraphStyle: paragraphStyle], range: NSMakeRange(0, attributedString.length))
            fullAttributedString.append(attributedString)
        }
        bulletTextView.attributedText = fullAttributedString
    }

    func createParagraphAttribute(tabStopLocation:CGFloat, defaultTabInterval:CGFloat, firstLineHeadIndent:CGFloat, headIndent:CGFloat) -> NSParagraphStyle {
        let paragraphStyle: NSMutableParagraphStyle = NSParagraphStyle.default.mutableCopy() as! NSMutableParagraphStyle
        let options:[NSTextTab.OptionKey:Any] = [:]
        paragraphStyle.tabStops = [NSTextTab(textAlignment: .left, location: tabStopLocation, options: options)]
        paragraphStyle.defaultTabInterval = defaultTabInterval
        paragraphStyle.firstLineHeadIndent = firstLineHeadIndent
        paragraphStyle.headIndent = headIndent
        return paragraphStyle
    }

Output:-

enter image description here

Upvotes: 5

Tom E
Tom E

Reputation: 1607

Set paragraph.firstLineHeadIndent to zero. This indents only lines starting with the second one. Currently, you are indenting all lines…

let paragraph = NSMutableParagraphStyle()
// paragraph.firstLineHeadIndent = 15
paragraph.headIndent = 15

Upvotes: 6

Mahendra Y
Mahendra Y

Reputation: 1949

Remove paragraph.firstLineHeadIndent = 15 from code...

let paragraph = NSMutableParagraphStyle()
paragraph.headIndent = 15

attributes = [
    NSAttributedStringKey.paragraphStyle: paragraph
]

attributedString = NSAttributedString(string: "\u{2022} Some text some text some text some text some text some text", attributes: attributes)
finalText.append(attributedString)

Please refer my sample code and screenshot

let style = NSMutableParagraphStyle()
        style.alignment = .left
        style.headIndent = 20

        let title = NSMutableAttributedString(string: "\u{2022} I need to add bulleted text to textView in iOS app. I am looking at this link and this one and following their ideas. This is my code:", attributes: [NSAttributedStringKey.paragraphStyle: style,NSAttributedStringKey.foregroundColor:UIColor.blue])

        let titleStr = NSMutableAttributedString(string: "\n\n\u{2022} I need to add bulleted text to textView in iOS app. I am looking at this link and this one and following their ideas. This is my code:", attributes: [NSAttributedStringKey.paragraphStyle: style,NSAttributedStringKey.foregroundColor:UIColor.blue])
        title.append(titleStr)
        titleLabel.attributedText = title

enter image description here

Upvotes: 10

Related Questions