ravelinx
ravelinx

Reputation: 1785

How to make a bullet list with Swift?

So I want to make something like this using swift and xcode:

enter image description here

Where I get each dot from an array. What I have thought is to make a UILabel and make a for loop that iterates over the array and in each iteration it adds to the label \u{2022} + content. I know \u{2022} is the dot point in unicode, the problem is that I need a way to make the list divided in two columns as shown and to make the dot point color yellow. This cant be done if I add the dots programmatically as I described above because the default color would be black. As the number of dots varies from the array contents for example if the array is of size 3 then only 3 dots would show 2 in the left and one to the right I need a way to meet this requirement, the other method I thought was of having two table views that takes half the screen and add this elements to each table view depending on the array. What should be the best practice here or is there a way to make this in the storyboard in a form that is dependent of an array.

Upvotes: 12

Views: 22555

Answers (4)

pableiros
pableiros

Reputation: 16062

For Swift 5, you can use this class:

class NSAttributedStringHelper {
    static func createBulletedList(fromStringArray strings: [String], font: UIFont? = nil) -> NSAttributedString {

        let fullAttributedString = NSMutableAttributedString()
        let attributesDictionary: [NSAttributedString.Key: Any]
    
        if let font = font {
            attributesDictionary = [NSAttributedString.Key.font: font]
        } else {
            attributesDictionary = [NSAttributedString.Key: Any]()
        }
   
        for index in 0..<strings.count {
            let bulletPoint: String = "\u{2022}"
            var formattedString: String = "\(bulletPoint) \(strings[index])"
        
            if index < strings.count - 1 {
                formattedString = "\(formattedString)\n"
            }
        
            let attributedString: NSMutableAttributedString = NSMutableAttributedString(string: formattedString, attributes: attributesDictionary)
            let paragraphStyle = NSAttributedStringHelper.createParagraphAttribute()
   attributedString.addAttributes([NSAttributedString.Key.paragraphStyle: paragraphStyle], range: NSMakeRange(0, attributedString.length))
        fullAttributedString.append(attributedString)
       }
    
        return fullAttributedString
    }

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

To use it:

let stringArray = ["first row", "second row", "third row"]
label.attributedText = NSAttributedStringHelper.createBulletedList(fromStringArray: stringArray, font: UIFont.systemFont(ofSize: 15))

Upvotes: 10

NFC.cool
NFC.cool

Reputation: 3312

I was not happy with the solutions above. So here is a Swifty function to get a bullet point list:

func bulletPointList(strings: [String]) -> NSAttributedString {
    let paragraphStyle = NSMutableParagraphStyle()
    paragraphStyle.headIndent = 15
    paragraphStyle.minimumLineHeight = 22
    paragraphStyle.maximumLineHeight = 22
    paragraphStyle.tabStops = [NSTextTab(textAlignment: .left, location: 15)]

    let stringAttributes = [
        NSAttributedString.Key.font: regularSystem(size: 22),
        NSAttributedString.Key.foregroundColor: UIColor.black,
        NSAttributedString.Key.paragraphStyle: paragraphStyle
    ]

    let string = strings.map({ "•\t\($0)" }).joined(separator: "\n")

    return NSAttributedString(string: string,
                              attributes: stringAttributes)
}

And this is how you use it:

label.numberOfLines = 0
label.attributedText = bulletPointList(strings: ["Foo", "Bar", "Lol"])

Upvotes: 14

simply_me
simply_me

Reputation: 384

use 2 labels inside a view for the columns. both labels being multulined

class Helper {

    static func bulletedList(strings:[String], textColor:UIColor, font:UIFont, bulletColor:UIColor, bulletSize:BulletSize) -> NSAttributedString {
        let textAttributesDictionary = [NSFontAttributeName : font, NSForegroundColorAttributeName:textColor]

        let bulletAttributesDictionary = [NSFontAttributeName : font.withSize(bulletSize.rawValue), NSForegroundColorAttributeName:bulletColor]
        let fullAttributedString = NSMutableAttributedString.init()

        for string: String in strings
        {
            let bulletPoint: String = "\u{2022}"
            let formattedString: String = "\(bulletPoint) \(string)\n"
            let attributedString: NSMutableAttributedString = NSMutableAttributedString(string: formattedString)
            let paragraphStyle = createParagraphAttribute()

            attributedString.addAttributes([NSParagraphStyleAttributeName: paragraphStyle], range: NSMakeRange(0, attributedString.length))
            attributedString.addAttributes(textAttributesDictionary, range: NSMakeRange(0, attributedString.length))

            let string:NSString = NSString(string: formattedString)
            let rangeForBullet:NSRange = string.range(of: bulletPoint)

            attributedString.addAttributes(bulletAttributesDictionary, range: rangeForBullet)
            fullAttributedString.append(attributedString)
        }
        return fullAttributedString
    }

    static func createParagraphAttribute() -> NSParagraphStyle {

        var paragraphStyle: NSMutableParagraphStyle
        paragraphStyle = NSParagraphStyle.default.mutableCopy() as! NSMutableParagraphStyle
        paragraphStyle.tabStops = [NSTextTab(textAlignment: .left, location: 15, options: NSDictionary() as! [String : AnyObject])]
        paragraphStyle.defaultTabInterval = 15
        paragraphStyle.firstLineHeadIndent = 0
        paragraphStyle.lineSpacing = 3
        paragraphStyle.headIndent = 10
        return paragraphStyle
    }
}

and simply use Helper.bulletedList to create your bulletted list as Attributed text for the label

Upvotes: 8

Zubair
Zubair

Reputation: 945

In Swift tabStop will work with the following changes

let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.minimumLineHeight = 0 // 0 means unlimited
paragraphStyle.maximumLineHeight = 0
paragraphStyle.firstLineHeadIndent = 30
paragraphStyle.headIndent = 0
paragraphStyle.tabStops = [NSTextTab(textAlignment: .left, location: 15, options: Dictionary<NSTextTab.OptionKey, Any>())]
paragraphStyle.defaultTabInterval = 10  //changing defaultTabInterval changes the distance between black dot & text
paragraphStyle.lineSpacing = 5

Upvotes: 2

Related Questions