Modifying entire NSMutableAttributedString using addAttribute: - iphone

I am looking for a way to color the first word in a sentence a different color to that of the rest of the sentence. METHOD_001 first colors the whole string white then re-colors the first 8 characters red. METHOD_002 colors the first 8 characters red, before using the string length to calculate the remaining characters and color them white.
METHOD_001 is definitely the best, but I am curious if there is a simpler way, I was expecting to find a NSMutableAttributedString addAttribute: that did not take a range and just applied the attribute to the whole string, it seems a bit of an oversight that all modifications to a NSMutableAttributedString require you to specify a range, am I missing something?
NB: Code includes hard coded values to aid readability.
// METHOD_001
NSMutableAttributedString *attrString_001 = [[NSMutableAttributedString alloc] initWithString:#"Distance 1720 mm" attributes:#{NSForegroundColorAttributeName : [UIColor whiteColor]}];
[attrString_001 addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:NSMakeRange(0, 8)];
[[self nameLabel] setAttributedText:attrString_001];
// METHOD_002
NSString *string = #"Distance 1720 mm";
NSUInteger stringLength = [string length];
NSMutableAttributedString *attrString_002 = [[NSMutableAttributedString alloc] initWithString:string];
[attrString_002 addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:NSMakeRange(0, 8)];
[attrString_002 addAttribute:NSForegroundColorAttributeName value:[UIColor whiteColor] range:NSMakeRange(9, (stringLength-9))];
[[self distanceLabel] setAttributedText:attrString_002];

Actually there is quite an easy way to do that. Even if you set an attributed text to your label, first it is stylized by the regular properties of the label, it is then your attributed string overrides corresponding ones. So if you do [distanceLabel setTextColor:[UIColor whiteColor]] beforehand (in storyboard or code) you can recolor only the needed parts by using attr. strings and achieve your desired effect.

Related

iOS 7 Applying kerning and line spacing to text

I have the following code which works flawlessly in iOS 6, problem is it has no effect whatsoever in iOS 7.
How do I apply kerning and line spacing in iOS 7?
+ (NSAttributedString *)attributedText:(NSString *)text inFont:(UIFont *)font {
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:text];
NSMutableParagraphStyle *style = [NSMutableParagraphStyle new];
style.lineSpacing = 5;
CGFloat kernSize = -0.6;
[attributedString addAttribute:NSParagraphStyleAttributeName value:style range:NSMakeRange(0, text.length)];
[attributedString addAttribute:NSKernAttributeName value:#(kernSize) range:NSMakeRange(0, text.length)];
return attributedString;
}
Maybe a duplicate to Why Does Kerning fail for NSAttributedString in IOS7
For some strange reason it does not work with the font Courier (in iOS7!) but with CourierNewPSMT.
Maybe try with different fonts.... here is a nice list of fonts on the iphone: http://iosfonts.com/

Finding the last line of text from UILable/UITextView

Here is the text present in my UILable...
"This list isn’t actually based on a straight popularity count; simply tallying the most-read verses results in a top 100 list that consists almost entirely of John 3:16 and verses from 1 Corinthians 13, Genesis 1, Romans 8, and Psalm 23. Our list instead considers instances in which BibleGateway.com users looked at three or fewer verses at one time."
How do i get the final line of text..ie.,"at three or fewer verses at one time." from my uilable.
Any solution is greatly appreciated.
I can give one idea . May this will help you.
UILabel *myLabel = [[UILabel alloc] initWithFrame:CGRectMake(50,50,200,350)];
myLabel.numberOfLines = 0;
myLabel.lineBreakMode = UILineBreakModeWordWrap;
myLabel.text = #"This is some text in a UILabel which is long enough to wrap around the lines in said UILabel. This is a test, this is only a test.";
[self.view addSubview:myLabel];
CGSize labelSize = [myLabel.text sizeWithFont:myLabel.font
constrainedToSize:myLabel.frame.size
lineBreakMode:UILineBreakModeWordWrap];
CGFloat labelHeight = labelSize.height;
NSLog(#"labelHeight = %f", labelHeight);
[myLabel release];
with above you can get height of label, then you can get the # of lines by dividing the height with some appropriate number which depends on the font size.
1) After this Get NSAttributedString from your UILabel.
2) From NSAttributedString you can get "\n" characters.
3) get last "\n" and extract value from this index to last index.

How to change the background of a UIimageview to hex value

I want to change the background color of my UIimageview. I am aware of how to do it like this
ColorBox.backgroundColor = [UIColor blueColor];
However, my program requires that the backgroundColor be set to a Hex color value. How do i set to a Hex color instead of a UIimage text color?
I have found a link which can answer you.
Please visit http://arstechnica.com/apple/guides/2009/02/iphone-development-accessing-uicolor-components.ars
Assuming you have the individual hex value for red, green and blue. This should work.
int red = [[NSString stringWithFormat:#"%d", redHex] intValue];
int green = [[NSString stringWithFormat:#"%d", greenHex] intValue];
int blue = [[NSString stringWithFormat:#"%d", blueHex] intValue];
[UIColor colorWithRed:red/255.0 green:green/255.0 blue:blue/255.0 alpha:1]
Or use this to parse the string:
How can I convert RGB hex string into UIColor in objective-c?

Why does NSString sizeWithFont: return the wrong size?

I need to work out the height of a UITextView from the top down to the cursor. I am trimming the text it contains (so it only goes up to the cursor) and then using NSString's sizeWithFont:constrainedToSize:lineBreakMode: method to work out the height, like so:
NSRange range;
range.location = noteTextView.selectedRange.location;
range.length = noteTextView.text.length - range.location;
NSString *string = [noteTextView.text stringByReplacingCharactersInRange:range withString:#""];
CGSize size = [string sizeWithFont:noteTextView.font
constrainedToSize:noteTextView.frame.size
lineBreakMode:UILineBreakModeWordWrap];
NSLog(#"height is: %f \n", size.height);
It does this every time I type anything.
The problem is, when I watch the NSLog as I type, it doesn't register a change of height until I have typed 4 characters on the new line. It is as if the sizeWithFont method is exactly four characters out. Here's a couple of screenshots showing what I mean:
Can anyone tell me what is going on?
#Vladimir's comment is right I think - an NSString doesn't take into account the margins of a UITextField.
You could try getting the text preceding the cursor and creating a new UITextField that only contains that text.
Then if you call [tempTextField sizeToFit] on your new text field then it's bounds should be the size you are looking for.

NSString sizeWithFont: returning inconsistent results? known bug?

I'm trying to create a simple custom UIView wich contain a string drawn with a single font, but where the first character is slightly larger.
I thought this would be easily implemented with two UILabel:s placed next to eachother.
I use NSString sizeWithFont to measure my string to be able to lay it out correctly.
But I noticed that the font baseline in the returned rectangle varies with +/- 1 pixel depending on the font size I set.
Here is my code:
NSString* ctxt = [text substringToIndex:1];
NSString* ttxt = [text substringFromIndex:1];
CGSize sz = [ctxt sizeWithFont: cfont ];
clbl = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, sz.width, sz.height)];
clbl.text = ctxt;
clbl.font = cfont;
clbl.backgroundColor = [UIColor clearColor];
[contentView addSubview:clbl];
CGSize sz2 = [ttxt sizeWithFont: tfont];
tlbl = [[UILabel alloc] initWithFrame:CGRectMake(sz.width, (sz.height - sz2.height), sz2.width, sz2.height)];
tlbl.text = ttxt;
tlbl.font = tfont;
tlbl.backgroundColor = [UIColor clearColor];
[contentView addSubview:tlbl];
If I use 12.0 and 14.0 as sizes, it works fine.
But if I instead use 13.0 and 15.0, then the first character is 1 pixel too high.
Is this a known problem?
Any suggestions how to work around it?
Creating a UIWebView with a CSS and HTML page seems way overkill for this. and more work to handle dynamic strings. Is that what I'm expected to do?
Found the answer...
Ofcourse, I also have to check the descender value on the font, and compensate for that in the layout.
New rect for the second label is:
CGRectMake(sz.width, (sz.height - sz2.height) + floor(cfont.descender - tfont.descender), sz2.width, sz2.height)
floor() is to make sure it snaps to pixel position, or the font will look blurry