How to size a symbol image in an attributed string - ios

I have a label where I am trying to put a symbol image at the start of the label and then some text after it. This works, but the symbol image never changes size. It doesn't matter what size I provide in the UIImageSymbolConfiguration, it stays small. If I take this code and put the image in a UIImageView, then the image gets larger as expected. Is there something wrong with anything I am doing here related to the symbol image configuration?
UILabel *label = [[UILabel alloc] init];
NSString *title = #"Some Text";
label.adjustsFontForContentSizeCategory = YES;
NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:#" %#", title] attributes:#{
NSFontAttributeName: [UIFont preferredFontForTextStyle:UIFontTextStyleBody],
NSForegroundColorAttributeName: [UIColor labelColor]
}];
UIImageSymbolConfiguration *configuration = [UIImageSymbolConfiguration configurationWithFont:[UIFont preferredFontForTextStyle:UIFontTextStyleLargeTitle]];
UIImage *squareImage = [[UIImage systemImageNamed:#"square.fill" withConfiguration:configuration] imageWithTintColor:[UIColor systemBlueColor]];
NSTextAttachment *imageAttachment = [NSTextAttachment textAttachmentWithImage:squareImage];
[string insertAttributedString:[NSAttributedString attributedStringWithAttachment:imageAttachment] atIndex:0];
label.attributedText = string;

I stumbled upon the same issue as I was building a similar feature today. It seems that symbols work slightly differently when embedded in text attachments: it's the font set on the attributed string that determines the size, not the configuration of the symbol itself.
With this in mind, you simply need to make sure the range of the icon in the attributed string has a font set:
UIFont *font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
[string addAttribute:NSFontAttributeName value:font range:NSMakeRange(0, 1)];
Note that you'll still need to configure the symbol if you intend to render using a different color. In this case, attributed strings will ignore the NSForegroundColorAttributeName attribute when rendering the symbol (resulting in a blank, zero-width symbol). I suspect this is because symbols have hierarchical colors, but I might be wrong.

Related

How to display 2 labels dynamically with different color?

See in Image, in that message "I still look back on that expe...." and after that one count value is there i.e (7) .
Here, message color is blue and count value i.e (7) is in green color.
My question is that, how to adjust both labels dynamically with different length and different color like example shown in image.
You can use NSAttributedString like in this example:
NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:#"I still look back on that expe.... (7)"];
[string setColorForText:#"I still look back on that expe...." withColor:[UIColor blueColor]];
[string setColorForText:#"(7)" withColor:[UIColor greenColor]];
mylabel.attributedText = string;
Or you can use the constraints in storyboard.
It is simple, you must use the Content Hugging Priority and Content Compression Resistance Priority values to reduce the first label to attach to the other label.
If you want I can explain you in detail how to do it.
EDIT:
You can try this code:
NSString *firstPart = #"I still look back on that expe....";
NSString *secondPart = #"(7)";
NSAttributedString *firstAttrStr = [[NSAttributedString alloc] initWithString:firstPart attributes:#{ NSForegroundColorAttributeName : [UIColor blueColor] }];
NSAttributedString *secondAttrStr = [[NSAttributedString alloc] initWithString:secondPart attributes:#{ NSForegroundColorAttributeName : [UIColor greenColor] }];
NSMutableAttributedString* result = [firstAttrStr mutableCopy];
[result appendAttributedString:secondAttrStr];
self.label.attributedText = result;
To add the images you can use NSTextAttachment.
Doing it with two labels is not the way you want to do it. A much better solution would be to use NSAttributedString.
struct MyMsg {
var text: String
var count: Int
}
let msg = MyMsg(text: "I still look back on that expe....", count: 7)
let contentString = NSMutableAttributedString(string: msg.text)
let countString = NSAttributedString(string: " \(msg.count)", attributes: [NSForegroundColorAttributeName: UIColor.green])
contentString.append(countString)
myLabel.attributedText = contentString

WatchKit, AttributedString formatting not working

I am building my first WatchKit App and am having troubles with NSAttributedString formatting as it does not seem to work as I'd expect ;)
This is my code:
UIFont *textFont = [UIFont fontWithName:#"Menlo" size:30];
UIFont *hlFont = [UIFont fontWithName:#"Menlo-Bold" size:30];
NSMutableAttributedString *information = [[NSMutableAttributedString alloc]initWithString:#"ADDED AN ENTRY OF " attributes:#{NSFontAttributeName : textFont}];
NSString *amountString = [NSString stringWithFormat:#"%.2f",(-1)*handler.amount.floatValue];
NSNumber *underline = [NSNumber numberWithInt:NSUnderlineStyleSingle];
NSAttributedString *amount = [[NSAttributedString alloc]initWithString:amountString attributes:#{NSFontAttributeName : hlFont, NSUnderlineStyleAttributeName : underline }];
NSAttributedString *to = [[NSMutableAttributedString alloc]initWithString:#" TO " attributes:#{NSFontAttributeName : textFont}];
NSString *categoryString = handler.category;
NSAttributedString *category = [[NSAttributedString alloc]initWithString:categoryString attributes:#{NSFontAttributeName : hlFont, NSUnderlineStyleAttributeName : underline }];
[information appendAttributedString:amount];
[information appendAttributedString:to];
[information appendAttributedString:category];
[_informationLabel setAttributedText:information];
and this the result:
Expectation
10.00 and Stuff should be underlined and in boldface.
Is there something fundamentally different to how attributed strings work on the watch than on iOS? What am I missing?
read through this: https://developer.apple.com/library/ios/documentation/General/Conceptual/WatchKitProgrammingGuide/TextandLabels.html
Solved it, the problem were the fonts #"Menlo".
By using
UIFont *textFont = [UIFont systemFontOfSize:20];
UIFont *hlFont = [UIFont systemFontOfSize:20];
the formatting with underlines works fine.
I don't believe you can programmatically set a label to be bold, italic, underlined....this has to be done through the actual interface in the storyboard.
According to this link
The attributes you can configure are
text
text color
font
min scale
alignment
lines
a potential workaround is to incorporate multiple labels, and set the ones you need to the right format (bold, underlined)

Change color and size portion of NSString with NSMutableAttributedString

Browsed through a few NSAttributedString examples but can't seem to get this working. I am trying to change the size and color of part of a NSMutableAttributedString.
I've tried a few variations of this:
NSMutableAttributedString *hintText = [[NSMutableAttributedString alloc] initWithString:#"This is red and huge and this is not"];
//Black and large
[hintText setAttributes:#{NSFontAttributeName:[UIFont fontWithName:#"Futura-Medium" size:20.0f], NSForegroundColorAttributeName:[UIColor blackColor]} range:NSMakeRange(0, 11)];
//Rest of text -- just futura
[hintText setAttributes:#{NSFontAttributeName:[UIFont fontWithName:#"Futura-Medium" size:16.0f]} range:NSMakeRange(12, ((hintText.length -1) - 12))];
This just changes the size of the text, not the color. Can someone point me in the right direction?
EDIT: I use this like so: myUILabel.attributedText = hintText;
When I'm trying to do something like this, I find it to be easier to build individual pieces (each of which is an NSAttributedString) and then "glue" them together with something like the following:
NSAttributedString *string1 = // Get the red and large string here
NSAttributedString *string2 = // Get the just futura string here
NSMutableAttributedString *hintText = [[NSMutableAttributedString alloc] init];
[hintText appendAttributedString:string1];
[hintText appendAttributedString:string2];
I find this makes it much easier to follow the logical flow and I've never found this way to have performance limitations that needed optimization.
Update:
FWIW, I got the following code to work as I believe the OP desires:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSMutableAttributedString *hintText = [[NSMutableAttributedString alloc] initWithString:#"This is red and huge and this is not"];
//Red and large
[hintText setAttributes:#{NSFontAttributeName:[UIFont fontWithName:#"Futura-Medium" size:20.0f], NSForegroundColorAttributeName:[UIColor redColor]} range:NSMakeRange(0, 20)];
//Rest of text -- just futura
[hintText setAttributes:#{NSFontAttributeName:[UIFont fontWithName:#"Futura-Medium" size:16.0f]} range:NSMakeRange(20, hintText.length - 20)];
[self.button setAttributedTitle:hintText forState:UIControlStateNormal];
}
Note that he was specifying [UIColor blackColor] and I updated that to [UIColor redColor]. Also, I updated the range calculations to include all of the characters in "This is red and huge".

NSMutableAttributedString UILabel is not retaining its attributes when selected

I am having issues with retaining an attributed NSMutableString. I have a UITableView who's each UITableViewCell has an attributed text. Setting the attributed text is no problem, but upon selection, the UITableViewCell's attributes is lost. This is my code in cellForRowAtIndexPath that sets the attribute:
NSMutableAttributedString *changesStyleString_h = [[NSMutableAttributedString alloc] initWithString:#"Attributes change!" attributes:#{NSFontAttributeName: [UIFont boldSystemFontOfSize:20], NSForegroundColorAttributeName:[UIColor yellowColor]}];
[changesStyleString_h addAttributes:#{ NSUnderlineStyleAttributeName:#(1)} range:NSMakeRange(11, 6)];
cell.mainLabel.attributedText = changesStyleString
might i point out that mainLabel is also a UILabel, no customization there. Any help in the right direction would be greatly appreciated!
I found that I needed to set attributes on the ENTIRE string, or it would do funky things.
NSString* string = #"1 - some string"
NSMutableAttributedString* string = [[NSMutableAttributedString alloc] initWithString:string];
[string setAttributes:#{NSForegroundColorAttributeName: accent, NSFontAttributeName: [UIFont fontWithName:#"HelveticaNeue-Bold" size:13.f]} range:NSMakeRange(0, 1)];
This would cause weird behavior when highlighting the cell.
However, when I did this:
[string setAttributes:#{NSForegroundColorAttributeName: [UIColor blackColor]} range:NSMakeRange(1, [labelTwo length] - 1)];
Everything seemed to work as expected.
Hope that helps!

Formatting UITableView Cells in iphone

I am developing an iphone app. In the image below I want the first name to be in plain font and the last name to be bold.. How can I do that? Please suggest me.. Please check this image:
Another questio..Now I think the reverse way but the problem here is the first line and second line you see are part of the same string. I want the first line to be bold and the second line to be in plain font. I am storing this in a dictionary. So my dictionary has a key and the value is a string of names and departments. I am unable to set the font. I tried to create two labels and tried to split the string according to the index and assign it to the labels I created. But, in this case the index keeps on changing as there might be a first name for a contact or there might not be any name.
In this case Prinicipal should be in plain font and name should be in bold
Please see the below image:
Starting OS 6.0 there is a property on the UILabel called attributedText which has NSAttributedString type (Available in iOS 3.2 and later.).
Here it is how I am using it:
NSDictionary *firstNameAttributes = #{ NSFontAttributeName : [UIFont fontWithName:#"Helvetica" size:18.0],
NSStrokeColorAttributeName : [UIColor blackColor]};
NSDictionary *lastNameAttributes = #{NSFontAttributeName : [UIFont fontWithName:#"Helvetica-Bold" size:20.0],
NSStrokeColorAttributeName : [UIColor blackColor]};
NSString* first = ... first name ..;
NSString* last = [NSString stringWithFormat:#" %#",... last name ....];
NSMutableAttributedString * name =
[[NSMutableAttributedString alloc] initWithString:first attributes:firstNameAttributes];
NSMutableAttributedString * lastName =
[[NSMutableAttributedString alloc] initWithString:last attributes:lastNameAttributes];
[name appendAttributedString:lastName];
[[cell textLabel] setAttributedText:name];
See also Introduction to Attributed String Programming Guide.
Since the label that you're showing the name string in defines the formatting and style, if you want to have different styles you need to have a different uilabel for each each style you want. Specifically, you will need a uilabel for the firstname: firstNameLabel.font = [UIFont systemFontOfSize:12]; and one for the lastname: lastNameLabel.font = [UIFont boldSystemFontOfSize:12];.
First place the first name string is the firstNameLabel then call [firstNameLabel sizeToFit] to fit the label text within it. Then use the frame of the firstNameLabel to place the lastNameLabel directly after it.
UILabel * firstNameLabel = [[UILabel alloc] initWithFrame:CGRectMake(10,10,100,25)];
firstNameLabel.tag = firstNameLabelTag //This should be a constant probably
firstNameLabel.font = [UIFont systemFontOfSize:12];
firstNameLabel.text = theStringRepresentingTheFirstName;
[firstNameLabel sizeToFit];
UILabel * lastNameLabel = [[UILabel alloc] initWithFrame:
CGRectMake(10+firstNameLabel.frame.size.width+2, 10, 100, 25)];
lastNameLabel.tag = lastNameLabelTag //This should be a constant probably
lastNameLabel.font = [UIFont boldSystemFontOfSize:12];
lastNameLabel.text = theLastNameString;.
[cell.contentView addSubview:firstNameLabel];
[cell.contentView addSubview:lastNameLabel];
And as for splitting the name string, you're probably pretty limited there. I would split on the first space and assume the first string is the last name (as in your first picture).
The principle case is similar, you need a label for each style that you want to present.
- (IBAction)buttonPressed:(UIButton *)sender {
NSString *title = [sender titleForState:UIControlStateNormal];
NSString *plainText = [NSString stringWithFormat:#"%# button pressed.", title];
NSMutableAttributedString *styledText = [[NSMutableAttributedString alloc] initWithString:plainText];
NSDictionary *attributes = #{ NSFontAttributeName : [UIFont boldSystemFontOfSize:self.statusLabel.font.pointSize]};
NSRange nameRange = [plainText rangeOfString:title];
[styledText setAttributes:attributes range:nameRange];
self.statusLabel.attributedText = styledText;
}
You have to create a custom UITableViewCell. http://icodeblog.com/2009/05/24/custom-uitableviewcell-using-interface-builder/

Resources