How do I make a bullet list using Swift?
So I want to do something like this using swift and xcode:
Where I am getting each point from the array. I thought about creating a UILabel and a for loop that iterates over the array, and in each iteration it adds \ u {2022} + content to the label. I know \ u {2022} is a point in Unicode, the problem is I need a way to split the list into two columns as shown and make the point color yellow. This cannot be done if I add dots programmatically as I described above, because the default color will be black. Since the number of points depends on the contents of the array, for example, if the array is of size 3, then only 3 points will display 2 on the left and one on the right, I need a way to satisfy this requirement, another method I thought was having two table views ,taking up half the screen and adding these elements to each table view depending on the array. What should be the best practice here or is there a way to do this in a storyboard in a form that depends on the array.
source to share
use two labels inside view for columns. both labels are multi-liner
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 just use Helper.bulletedList
to create your bulleted list as attributed text for the label
source to share
I was not happy with the solutions above. So here's the Swifty function to get a list of markers:
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 = [
NSAttributedStringKey.font: UIFont.systemFont(ofSize: 12),
NSAttributedStringKey.foregroundColor: UIColor.black,
NSAttributedStringKey.paragraphStyle: paragraphStyle
]
let string = strings.map({ "•\t\($0)" }).joined(separator: "\n")
return NSAttributedString(string: string,
attributes: stringAttributes)
}
And here's how you use it:
label.numberOfLines = 0
label.attributedText = bulletPointList(strings: ["Foo", "Bar", "Lol"])
source to share
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 font != nil {
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 this:
let stringArray = ["first row", "second row", "third row"]
label.attributedText = NSAttributedStringHelper.createBulletedList(fromStringArray: stringArray, font: UIFont.systemFont(ofSize: 15))
source to share
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
source to share