Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make a bullet list with Swift?

Tags:

ios

swift

swift3

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.

like image 209
ravelinx Avatar asked Mar 29 '17 02:03

ravelinx


4 Answers

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))
like image 187
pableiros Avatar answered Oct 18 '22 03:10

pableiros


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"])
like image 30
Nico S. Avatar answered Oct 18 '22 02:10

Nico S.


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

like image 22
simply_me Avatar answered Oct 18 '22 04:10

simply_me


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
like image 42
Zubair Avatar answered Oct 18 '22 02:10

Zubair