Reputation: 2948
so i have a String which looks like this : Swift , VisualBasic , Ruby
i wanna convert this string to something like this :
basically i wanna create a background behind a single word , yeah i can use the NSTokenField libraries for getting this behaviour but my text is not manually entered by user its pre structured (from an array) and i dont want the whole behaviour of NSTokeField i just want the appearance like this and selection (by selection i mean to clear a word at one single tap on backspace , the whole word not a letter )
well i know how to change the colour of a text something like this
func getColoredText(text: String) -> NSMutableAttributedString {
let string:NSMutableAttributedString = NSMutableAttributedString(string: text)
let words:[String] = text.componentsSeparatedByString(" ")
var w = ""
for word in words {
if (word.hasPrefix("{|") && word.hasSuffix("|}")) {
let range:NSRange = (string.string as NSString).rangeOfString(word)
string.addAttribute(NSForegroundColorAttributeName, value: UIColor.redColor(), range: range)
w = word.stringByReplacingOccurrencesOfString("{|", withString: "")
w = w.stringByReplacingOccurrencesOfString("|}", withString: "")
string.replaceCharactersInRange(range, withString: w)
}
}
return string
}
but i dont know how to achieve what i want if somebody can provide me some guidance then it'll be so helpful for me
P.s if my question is not clear enough then please let me know i'll add some more details
Upvotes: 2
Views: 9966
Reputation: 15331
It's going to be much easier to just use several UILabel
s if you want to get rounded corners.
If that's acceptable you can first generate an array of attributed strings like:
func getAttributedStrings(text: String) -> [NSAttributedString]
{
let words:[String] = text.componentsSeparatedByString(" , ")
let attributes = [NSForegroundColorAttributeName: UIColor.whiteColor(), NSBackgroundColorAttributeName: UIColor.blueColor()]
let attribWords = words.map({
return NSAttributedString(string: " \($0) ", attributes: attributes)
})
return attribWords
}
For each attributed string we need to create UILabel
. To do so we can create a function that passes in an NSAttributedString
and returns a UILabel
:
func createLabel(string:NSAttributedString) ->UILabel
{
let label = UILabel()
label.backgroundColor = UIColor.blueColor()
label.attributedText = string
label.sizeToFit()
label.layer.masksToBounds = true
label.layer.cornerRadius = label.frame.height * 0.5
return label
}
Now we'll convert our input string into labels by saying:
let attribWords = getAttributedStrings("Java , Swift , JavaScript , Objective-C , Ruby , Pearl , Lisp , Haskell , C++ , C")
let labels = attribWords.map { string in
return createLabel(string)
}
Now we just need to display them in a view:
let buffer:CGFloat = 3.0
var xOffset:CGFloat = buffer
var yOffset:CGFloat = buffer
let view = UIView(frame: CGRect(x: 0.0, y: 0.0, width: 320.0, height: 400.0))
view.backgroundColor = UIColor.lightGrayColor()
for label in labels
{
label.frame.origin.x = xOffset
label.frame.origin.y = yOffset
if label.frame.maxX > view.frame.maxX
{
xOffset = buffer
yOffset += label.frame.height + buffer
label.frame.origin.x = xOffset
label.frame.origin.y = yOffset
}
view.addSubview(label)
xOffset += label.frame.width + buffer
}
We can also at this point resize our view to the height of the labels by saying:
if let labelHeight = labels.last?.frame.height
{
view.frame.height = yOffset + labelHeight + buffer
}
Throwing this code in a swift playground results in:
If you can't use labels, if you want an editable UITextView
for example, I would give up on rounded corners and just say something like:
let attribWords = getAttributedStrings("Java , Swift , JavaScript , Objective-C , Ruby , Pearl , Lisp , Haskell , C++ , C")
let attribString = NSMutableAttributedString()
attribWords.forEach{
attribString.appendAttributedString(NSAttributedString(string: " "))
attribString.appendAttributedString($0)
}
textView.attributedText = attribString
Upvotes: 8