I want to change color to all characters in string. But my code is giving just last character in string. I want to append characters in attributed string. How can I do this ?
My Code :
func test(){
var str:String = "test string"
for i in 0...count(str)-1{
var test = str[advance(str.startIndex, i)]
var attrString = NSAttributedString(string: toString(test), attributes: [NSForegroundColorAttributeName: rainbowColors()])
label.attributedText = attrString
}
}
In this case you don't need to append characters if you want each character to have the same rainbow color. You could do the following:
label.attributedText = NSAttributedString(string: str, attributes: [NSForegroundColorAttributeName: rainbowColors()])
If you want to append characters you need to use NSMutableAttributedString. It has a method called append.
Given the fact that you want a different color for each index do the following:
var str:String = "test string"
var attributedString = NSMutableAttributedString()
for (index, character) in enumerate(str) {
attributedString.appendAttributedString(NSAttributedString(string: String(character), attributes: [NSForegroundColorAttributeName: colorForIndex(index)]))
}
label.attributedText = attributedString
colorForIndex is a function you need to implement to get the rainbow color for that particular index
func colorForIndex(index: Int) -> UIColor {
let color = // your function to get the color
return color
}
If you need help to implement that function take a look at this question iOS rainbow colors array
Related
I'm having a certain sentence. I have to give black color to four words in that sentence.
This is how I have attempted that...
In viewDidLoad,
rangeArray = ["Knowledge","Events","Community","Offers"]
for text in rangeArray {
let range = (bottomTextLabel.text! as NSString).range(of: text)
let attribute = NSMutableAttributedString.init(string: bottomTextLabel.text!)
attribute.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.black , range: range)
self.bottomTextLabel.attributedText = attribute
}
But with this code, instead of having black color for all 4 words, I get only the word 'Offers' in black color. What am I doing wrong...?
In your code, you are updating the self.bottomTextLabel.attributedText for each run of the for loop.
Instead of that you must
create an NSMutableAttributedString using the sentence,
add all the relevant attributes as per your rangeArray and
then at last set that attrStr it as attributedText of bottomTextLabel.
Here is what I mean to say,
if let sentence = bottomTextLabel.text {
let rangeArray = ["Knowledge","Events","Community","Offers"]
let attrStr = NSMutableAttributedString(string: sentence)
rangeArray.forEach {
let range = (sentence as NSString).range(of: $0)
attrStr.addAttribute(.foregroundColor, value: UIColor.black, range: range)
}
self.bottomTextLabel.attributedText = attrStr
}
I just want to change color of some word in my Label's string.
What I want to do is:
How Im trying to do:
But it doesnt work and it says: 'NSMutableRLEArray replaceObjectsInRange:withObject:length:: Out of bounds'
So I need an advice to do this easy thing, and I need a trick to do this. You guys can send your way.
Try this, your attributed string has no value when you try get the range of the string. You got to give the attributed string a string value before that. You
let descriptionLabel: UILabel = {
let label = UILabel()
// String variable containing the text.
let fullString = "mehmet alper tabak"
// Choose wwhat you want to be colored.
let coloredString = "alper"
// Get the range of the colored string.
let rangeOfColoredString = (fullString as NSString).range(of: coloredString)
// Create the attributedString.
let attributedString = NSMutableAttributedString(string:fullString)
attributedString.setAttributes([NSForegroundColorAttributeName: UIColor.red],
range: rangeOfColoredString)
label.attributedText = attributedString
return label
}()
descriptionLabel.frame = CGRect(x: 50, y: 50, width: 140, height: 100)
self.view.addSubview(descriptionLabel)
Or you can do an extension of UILabel.
extension UILabel {
func colorString(text: String?, coloredText: String?, color: UIColor? = .red) {
let attributedString = NSMutableAttributedString(string: text!)
let range = (text! as NSString).range(of: coloredText!)
attributedString.setAttributes([NSForegroundColorAttributeName: color!],
range: range)
self.attributedText = attributedString
}
To use it.
self.testLabel.colorString(text: "mehmet alper tabak",
coloredText: "alper")
It is out of bounds because myMutableString is empty at the time that you are trying to set attributes. Try instead:
let myMutableString = NSMutableAttributedString.init(string: label.text)
Create attributedString1 with first color
let attributedString1 = NSAttributedString(string: "robert plant ", attributes: [NSForegroundColorAttributeName: color1])
Create attributedString2 with second color
let attributedString1 = NSAttributedString(string: "with queen", attributes: [NSForegroundColorAttributeName: color2])
Add them to myMutableString
myMutableString.append(attributedString1)
myMutableString.append(attributedString1)
I am trying to add color to 2 words in a string. This is the code I am using:
var HighScore:Int = 0
var CurrentScore:Int = 0
let stringOne = "You have managed to score \(CurrentScore). Current record is \(self.HighScore). Play again and give it another try!"
let stringTwo = "\(CurrentScore)"
let stringThree = "\(HighScore)"
let range1 = (stringOne as NSString).range(of: stringTwo)
let range2 = (stringOne as NSString).range(of: stringThree)
let attributedText = NSMutableAttributedString.init(string: stringOne)
attributedText.addAttribute(NSForegroundColorAttributeName, value: UIColor.init(netHex: 0x00b4ff) , range: range1)
attributedText.addAttribute(NSForegroundColorAttributeName, value: UIColor.init(netHex: 0x00b4ff) , range: range2)
gameOverDescriptionLabel.attributedText = attributedText
The problem I have is that if CurrentScore and HighScore is the same(ex: 2 & 2) the color on the range2 still stays white, but if they are not equal(2 & 1 or 1 & 2) both gets the color I have choosen.
Any suggestions?
Add this to the top or bottom of your .swift file:
extension NSMutableAttributedString {
func bold(_ text:String) -> NSMutableAttributedString {
let attrs:[String:AnyObject] = [NSForegroundColorAttributeName: UIColor.init(netHex: 0x00b4ff)]
let boldString = NSMutableAttributedString(string:"\(text)", attributes:attrs)
self.append(boldString)
return self
}
func normal(_ text:String)->NSMutableAttributedString {
let normal = NSAttributedString(string: text)
self.append(normal)
return self
}
}
To code below is the usage, you can edit it how you'd like, but I have made it so you can easy just copy&paste it to your project:
let formattedString = NSMutableAttributedString()
formattedString
.normal("You have managed to score ")
.bold("\(CurrentScore)")
.normal(". Current record is ")
.bold("\(HighScore)")
.normal(". Play again and give it another try!")
gameOverDescriptionLabel.attributedText = formattedString
If the current score and high score are the same string, searching for the latter finds the former (because the search starts at the beginning).
There are lots of other, better ways to do this.
Perform the second search in a range starting after the result of the first search (range(of:) has a range: parameter, but you are not using it)
Instead of looking for the range of the high score, search for the surrounding boilerplate ("You have managed to score" and so on) and figure out where the numbers must be.
Use NSScanner or regular expressions to find the numerical expressions embedded in the string.
My favorite: mark each of the numbers with an "invisible" attribute and search for that attribute so that you can find the numbers reliably (example here).
A solution without searching for the range would be to create 2 separate NSMutableAttributedString for current score and high score, and then append everything together.
let currentScoreString = NSMutableAttributedString(...)
let highscoreString = NSMutableAttributedString(...)
let finalString = NSMutableAttributedString(string: "You have managed to score ").append(currentScoreString)....
//MARK: forgroundColor
open var foregroundColor: UIColor? {
didSet {
textAttributes[NSForegroundColorAttributeName] = foregroundColor
self.attributedText = NSAttributedString(string: self.text, attributes: textAttributes)
}
}
//MARK: backgroundColor
open var textBackgroundColor: UIColor? {
didSet {
textAttributes[NSBackgroundColorAttributeName] = textBackgroundColor
self.attributedText = NSAttributedString(string: self.text, attributes: textAttributes)
}
}
I have this code in my hands:
if let text = trimText?.mutableCopy() as? NSMutableString {
text.insertString("\(prefix) ", atIndex: 0)
textStorage.replaceCharactersInRange(range, withString: text as String)
}
When I try to change my text as:
text = attributedTextFunc(text)
where
func attributedTextFunc(str: NSString) -> NSAttributedString {
var attributedString = NSMutableAttributedString(string: str as String, attributes: [NSFontAttributeName:UIFont.systemFontOfSize(15.0)])
let boldFontAttribute = [NSFontAttributeName: UIFont.boldSystemFontOfSize(15.0)]
attributedString.addAttributes(boldFontAttribute, range: str.rangeOfString("More"))
return attributedString
}
and I get this error:
Cannot assign value of type 'NSAttributedString' to type 'NSMutableString'
How can I make it bold?
You cannot assing NSAttributedString to text. It's two different types.
String is not subclassed from NSAttributedString.
You should set:
attributedText = attributedTextFunc(text)
Then if you want to present it on UILabel
label.attributedText = attributedText
UPDATE
Struct String doesn't know anything about UIKit and Bold styles.
NSAttributedString knows about UIKit and contains any text styles you want
UPDATE 2
In your case
ReadMoreTextView.attributedTrimText = attributedText
You cannot reassign text because:
text is constant (let)
text is NSMutableString, but attributedTextFunc return NSAttributedString
You have to store result of attributedTextFunc in variable as a NSAttributeString and set attributeText of UILabel instead of text
if let text = trimText?.mutableCopy() as? NSMutableString {
// ...
let attributeText = attributedTextFunc(text)
someLabel.attributeText = attributeText
}
Use this code and pass your normal String and Bold String (which is needed to be bold).
func attributeStrings(first: String, second : String) -> NSMutableAttributedString{
let myNormalAttributedTitle = NSAttributedString(string: first,
attributes: [NSFontAttributeName : UIFont.boldSystemFontOfSize(15)])
let myAttributedTitle = NSAttributedString(string: second,
attributes: [NSForegroundColorAttributeName : UIColor.blackColor()])
let result = NSMutableAttributedString()
result.appendAttributedString(myNormalAttributedTitle)
result.appendAttributedString(myAttributedTitle)
return result
}
and assign the return value of this function to
someLabel.attributeText = attributeStrings("My Name is", second : "Himanshu")
It is because, your text is type of NSMutableString and your function attributedTextFunc is type of NSString.
That is the problem so just change it from NSString to NSMutableString.
I'm trying to set some attributes of a string in code, but can't get NSAttributedString to work. This is the function, that's supposed to change the string:
func getAttributedString(string: String) -> NSAttributedString
{
var attrString = NSMutableAttributedString(string: string)
var attrs = [NSFontAttributeName : UIFont.boldSystemFontOfSize(18.0)]
attrString.setAttributes(attrs, range: NSMakeRange(0, attrString.length))
return attrString
}
And this is how I use it:
if (self.product.packageDimensions != nil) {
self.descriptionLabel.text =
self.descriptionLabel.text + self.getAttributedString("Package dimensions:").string +
"\n\(self.product.packageDimensions) \n"
}
But the font stays the same. What am I doing wrong ?
You make 2 errors in your code.
setAttributes needs a Dictionary, not an Array
when you use the string attribute, you will only get a String, all attributes are lost.
To add or change attributes to a attributedString it has to be mutable. You only get a NSMutableString from the attributedText attribute. If you want to change it create a mutable version from it and change it. Then you may set the attributedText to the new mutable version.
If you can give the attributed string as an argument, I will give you an example that works:
func setFontFor(attrString: NSAttributedString) -> NSMutableAttributedString {
var mutableAttrString: NSMutableAttributedString = NSMutableAttributedString(attributedString: attrString)
let headerStart: Int = 0
let headerEnd: Int = 13
mutableAttrString.addAttribute(NSFontAttributeName, value: UIFont.boldSystemFontOfSize(18.0), range: NSMakeRange(headerStart, headerEnd))
return mutableAttrString
}
Usage:
myLabel.attributedText = setFontFor(myLabel.attributedText)
As you can see I used the attributedText property of the UILabel class, it also works for UITextView and others. If you have another label, you can create a new NSAttributedString with the initializer NSAttributedString(normalString) as you already used in the question code.
if (self.product.packageDimensions != nil) {
self.descriptionLabel.attributedText =
self.descriptionLabel.attributedText + self.getAttributedString("Package dimensions:").string +
"\n\(self.product.packageDimensions) \n"
}
You should use the attributedText method