Update NSMutableAttributedString in another class - ios

I have a UIButton class with a NSMutableAttributedString as the title (for the formatting).
I would like to now change the titleColor of the button text from my vc class because it has been'selected'.
I can do it fine as a normal button title. But as a NSMutableAttributedString - no dice.
Some questions/advice: As the custom class view is already a button - should my color update happen in that class - and not from the vc? Just tell it to update and bake the color in the custom class?
Do I expose the NSMutableAttributedString property for the button's title so that I can access from my VC and change the color? This way I could also pass in new text as well as a new color.
In my CircleButton m file
NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
[style setAlignment:NSTextAlignmentCenter];
[style setLineBreakMode:NSLineBreakByWordWrapping];
UIFont *font1 = [UIFont fontWithName:#"Futura" size:20.0f];
NSDictionary *dict1 = #{NSUnderlineStyleAttributeName:#(NSUnderlineStyleNone),
NSFontAttributeName:font1,
NSForegroundColorAttributeName:textClr,
NSParagraphStyleAttributeName:style};
attributedTText = [[NSAttributedString alloc] initWithString:btnTxt attributes:dict1];
[[button titleLabel] setNumberOfLines:0];
[[button titleLabel] setLineBreakMode:NSLineBreakByWordWrapping];
[button setAttributedTitle:attributedTText forState:UIControlStateNormal];
[button setTitleColor:textClr forState:UIControlStateNormal];

Related

iOS: Can I change color part of a Button Tittle?

I am new in iOS. I want to know how can I change the color for each part of UIButton title.
For example, a part of title in my UIButton is black and another the part of title in my UIButton is yellow
This is the describe image
Any help would be appreciated
U can use NSMutableAttributedString then add it to button with [button setAttributedTitle:attString forState:UIControlStateNormal];
To change color of a range in the Attribute String, read this, basically its just 1 of the attribute dictionary
Read this SO Question
I solve my question by using the code below.
For UILabel
NSMutableAttributedString *text =
[[NSMutableAttributedString alloc]
initWithAttributedString: self.lblFriendBand.attributedText];
[text addAttribute:NSForegroundColorAttributeName
value:[UIColor redColor]
range:NSMakeRange(1, 2)];
[self.lblFriendBand setAttributedText: text];
For UIButton
NSMutableAttributedString *text2 =
[[NSMutableAttributedString alloc]
initWithAttributedString: self.btnFriendName.titleLabel.attributedText];
[text2 addAttribute:NSForegroundColorAttributeName
value:[UIColor redColor]
range:NSMakeRange(1, 2)];
[self.btnFriendName setAttributedTitle:text2 forState:UIControlStateNormal];

iOS How to draw text in UIViewController

I'm feeling very stupid right now.
I'm trying to draw text onto a UIViewController.
I'm using Xcode 5 and started with a simple Single Page project, and have done nothing else except adding this code to the ViewController.m:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
CGRect myRect=CGRectMake(0,0,self.view.bounds.size.width,self.view.bounds.size.height);
UIFont *myFont=[UIFont fontWithName:#"Helvetica" size:50];
NSMutableParagraphStyle *paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
paragraphStyle.lineBreakMode = NSLineBreakByTruncatingTail;
paragraphStyle.alignment = NSTextAlignmentRight;
NSMutableDictionary *attributes = [[NSMutableDictionary alloc] init];
[attributes setObject:myFont forKey:NSFontAttributeName];
[attributes setObject:paragraphStyle forKey:NSParagraphStyleAttributeName];
[attributes setObject:[NSNumber numberWithFloat:4] forKey:NSStrokeWidthAttributeName];
[attributes setObject:[UIColor whiteColor] forKey:NSStrokeColorAttributeName];
[#"test" drawInRect:myRect withAttributes:attributes];
// draw fill
[attributes removeObjectForKey:NSStrokeWidthAttributeName];
[attributes removeObjectForKey:NSStrokeColorAttributeName];
[attributes setObject:[UIColor blackColor] forKey:NSForegroundColorAttributeName];
[#"test" drawInRect:myRect withAttributes:attributes];
}
It runs without errors but produces no text - why?
The drawInRect method doesn't work with UIViewController. That method is a UIView method and will only work if your class is a UIView class or subclass.
So, as mentioned above, you can just set your text attributes on a UILabel and display them wherever you like on the screen. It should give you the same effect. Optionally, you could try to change the subclass to UIView, but that could require more modifications to your code than you would like.
To add to tfrank377, you can add labels programmatically with something like
UILabel *addLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 10, 100, 30)];
[self.view addSubview:addLabel];
addLabel.text = #"Hello World";
which will display text on your UIView.

UIButton - Lead Text with Icon

I am trying to figure out a solution to creating a UIButton, with centred text which has a UIImage (icon) leading the text, so its sites just in front of the button title.
I, however am struggling to think up a way of doing this as you cannot retrieve the position of the text. Any thoughts? This must be a fairly common thing to do.
Use this code
UIButton *scoreButton=[UIButton buttonWithType:UIButtonTypeCustom];
scoreButton.frame=CGRectMake(0,0,100, 100);
//scoreButton.contentEdgeInsets=UIEdgeInsetsMake(0, 0, 0, 2);
scoreButton.contentHorizontalAlignment=UIControlContentHorizontalAlignmentLeft;
scoreButton.titleLabel.font=[UIFont boldSystemFontOfSize:13];
[scoreButton setTitleColor:[UIColor colorWithRed:0.9411 green:0.5647 blue:.2916 alpha:YES] forState:UIControlStateNormal];
[scoreButton addTarget:self action:nil forControlEvents:UIControlEventTouchUpInside];
UIImageView *scoreButtonImageView=[[UIImageView alloc]init];
scoreButtonImageView.frame=CGRectMake(0,35,30 ,30);
scoreButtonImageView.image=[UIImage imageNamed:#"leaderboard_score_button.png"];
[scoreButton addSubview:scoreButtonImageView];
Use UIEdgeInsetsMake to set your text start and end points.
In this way your image will be on the extreme left hand side and you can write text after the image
Create a UIView subclass that has a UIImageView and UILabel. Position the label to the right of the image view within this view. Add this view to your button and position it horizontally and vertically centred.
I think , it will help you. Always careful with setImage: and setBackgroundImage:
UIButton *yourBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[yourBtn setBackgroundImage:bgImage forState:UIControlStateNormal];
[yourBtn setBackgroundImage:bgImage forState:UIControlStateHighlighted];
[yourBtn setTitle:titleString forState:UIControlStateNormal];
Use following method :
UIImageView *yourPlusSign = [UIImageView alloc]initWithImage:[UIImage imageNamed:#"yourPlusSignImageTitle"];
yourPlusSign.frame = CGRectMake(x, y, width, height);//choose values that fit properly inside the frame of your baseButton
//or grab the width and height of yourBaseButton and change accordingly
yourPlusButton.contentMode=UIViewContentModeScaleAspectFill;//or whichever mode works best for you
[yourBaseButton addSubview:yourPlusSign];
Here is Ref : Add an image inside UIButton as an accesory
you can also subclass UIButton it is a better way to do it.
If you use font images like me you can do it with a NSParagraphStyle
NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
[style setAlignment:NSTextAlignmentCenter];
UIFont *font1 = [UIFont fontWithName:#"Avenir-Roman" size:14.0];
UIFont *font2 = [UIFont fontWithName:#"Icon-Moon" size:12.0];
NSDictionary *fontSyle1 = #{NSUnderlineStyleAttributeName:#(NSUnderlineStyleNone),
NSFontAttributeName:font1,
NSParagraphStyleAttributeName:style};
NSDictionary *fontStyle2 = #{NSUnderlineStyleAttributeName:#(NSUnderlineStyleNone),
NSFontAttributeName:font2,
NSParagraphStyleAttributeName:style};
NSMutableAttributedString *attString = [[NSMutableAttributedString alloc] init];
[attString appendAttributedString:[[NSAttributedString alloc] initWithString:[IcoMoon iconString:k12_ADD_NOTE] attributes:fontStyle2]];
[attString appendAttributedString:[[NSAttributedString alloc] initWithString:#" Add Note" attributes:fontStyle1]];
[_addNewBtn setAttributedTitle:attString forState:UIControlStateNormal];
[[_addNewBtn titleLabel] setNumberOfLines:0];
_addNewBtn.layer.borderColor = [UIColor lightGrayColor].CGColor;
_addNewBtn.layer.borderWidth = 1;
[_addNewBtn setBackgroundColor:[UIColor whiteColor]];
[_addNewBtn setTintColor:[UIColor darkGrayColor]];
This where you can get icon fonts https://icomoon.io/
This part is part of a way to convert char's to strings
[IcoMoon iconString:k12_ADD_NOTE]
you can find out more by going to https://github.com/sebastienwindal/IOSIcoMoon

How can I set the color and alignment of attributed text in a UITextView in iOS 7?

The formatting of my textViews worked fine in iOS 6, but no longer in iOS 7. I understand with Text Kit much of the under the hood stuff has changed. It's become really quite confusing, and I'm hoping someone can help straighten it out a bit by helping me with something as simple as this.
My static UITextView originally was assigned a value for it's textColor and textAlignment properties. Then I made a NSMutableAttributedString, assigned it an attributes, then assigned it to the textView's attributedText property. The alignment and color no longer take effect in iOS 7.
How can I fix this? If these properties take no effect, than why do they exist anymore? Here's the creation of the textView:
UITextView *titleView = [[UITextView alloc]initWithFrame:CGRectMake(0, 90, 1024, 150)];
titleView.textAlignment = NSTextAlignmentCenter;
titleView.textColor = [UIColor whiteColor];
NSMutableAttributedString *title = [[NSMutableAttributedString alloc]initWithString:#"Welcome"];
UIFont *font = [UIFont fontWithName:#"Avenir-Light" size:60];
[title addAttribute:NSParagraphStyleAttributeName value:font range:NSMakeRange(0, title.length)];
titleView.attributedText = title;
[self.view addSubview:titleView];
Curious, the properties are taken into account for UILabel but not for UITextView
Why don't you just add attributes for color and alignment to the attributed string similar to the way you are doing with the font?
Something like:
NSMutableAttributedString *title = [[NSMutableAttributedString alloc]initWithString:#"Welcome"];
UIFont *font = [UIFont fontWithName:#"Avenir-Light" size:60];
[title addAttribute:NSFontAttributeName value:font range:NSMakeRange(0, title.length)];
//add color
[title addAttribute:NSForegroundColorAttributeName value:[UIColor whiteColor] range:NSMakeRange(0, title.length)];
//add alignment
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
[paragraphStyle setAlignment:NSTextAlignmentCenter];
[title addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, title.length)];
titleView.attributedText = title;
Edit: Assign the text first, then change the properties and this way it works.
UITextView *titleView = [[UITextView alloc]initWithFrame:CGRectMake(0, 90, 1024, 150)];
//create attributed string and change font
NSMutableAttributedString *title = [[NSMutableAttributedString alloc]initWithString:#"Welcome"];
UIFont *font = [UIFont fontWithName:#"Avenir-Light" size:60];
[title addAttribute:NSFontAttributeName value:font range:NSMakeRange(0, title.length)];
//assign text first, then customize properties
titleView.attributedText = title;
titleView.textAlignment = NSTextAlignmentCenter;
titleView.textColor = [UIColor whiteColor];

Title color of UIButton won't change on highlighted/selected but background color will

This has been a very odd process.
I have an IBOutletCollection of UIButtons. I loop through the collection and create them like this (the displayHourButtons is called from viewWillAppear):
- (void)displayHourButtons
{
// Counter
NSUInteger b = 0;
// Set attributes
UIFont *btnFont = [UIFont fontWithName:#"Metric-Semibold" size:13.0];
UIColor *btnTextColor = [UIColor colorWithRed:(147/255.0f) green:(147/255.0f) blue:(147/255.0f) alpha:1.0];
NSNumber *btnTracking = [NSNumber numberWithFloat:0.25];
NSMutableParagraphStyle *btnStyle = [[NSMutableParagraphStyle alloc] init];
[btnStyle setLineSpacing:2.0];
NSDictionary *btnAttrs = [NSDictionary dictionaryWithObjectsAndKeys:
btnFont, NSFontAttributeName,
btnTextColor, NSForegroundColorAttributeName,
btnTracking, NSKernAttributeName, nil];
// CREATE THE BUTTONS
for (UIButton *hourButton in hourButtons) {
// I'm using the attributed string for something else
// later in development that I haven't got to yet.
// I simplified the string for this example's sake.
NSString *btnTitleText = [NSString stringWithFormat:#"Button %lu", (unsigned long)b];
NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc]
initWithString:btnTitleText
attributes:btnAttrs];
[attributedText addAttribute:NSParagraphStyleAttributeName
value:btnStyle
range:NSMakeRange(0, btnTitleText.length)];
CALayer *btnLayer = [hourButton layer];
[btnLayer setMasksToBounds:YES];
[btnLayer setCornerRadius:19.0f];
[hourButton setTag:b];
[hourButton setContentEdgeInsets:UIEdgeInsetsMake(5.0, 1.0, 0.0, 0.0)];
[hourButton setAttributedTitle:attributedText forState:UIControlStateNormal];
[hourButton setContentHorizontalAlignment:UIControlContentHorizontalAlignmentCenter];
[hourButton setContentVerticalAlignment:UIControlContentVerticalAlignmentCenter];
hourButton.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
[hourButton addTarget:self action:#selector(showHour:) forControlEvents:UIControlEventTouchUpInside];
b++;
}
}
When one of the buttons is clicked, per the action showHour: is called:
- (IBAction)showHour:(id)sender
{
[self.hourButtons enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
UIButton *button = (UIButton *)obj;
if (button != sender && button.enabled) {
// This is applied. I know because I tested it with redColor
[button setBackgroundColor:[UIColor clearColor]];
// Doesn't change, stays the gray set initially
[button setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
}
else {
// This is applied
[button setBackgroundColor:[UIColor colorWithRed:(169/255.0f) green:(234/255.0f) blue:(255/255.0f) alpha:1.0]];
// This is not
[button setTitleColor:[UIColor whiteColor] forState:(UIControlStateNormal | UIControlStateSelected | UIControlStateHighlighted)];
}
}];
// displayHour uses the tag to change labels, images, etc.
[self displayHour:(long int)[sender tag]];
}
I tried all sorts of crazy things to get the UIImage to be in a selected state, but nothing worked. This enumerateObjects deal is the only thing that has worked. That's why I say this has been an odd process. I guess buttons don't stay active indefinitely?
Anyways, MY QUESTION: Is there a certain reason why the title color isn't changing? Just the background? I suspect it has something to do with the background not being set initially, but I couldn't explain why.
Thanks!
UPDATED
Per #Timothy Moose's answer, below is the updated code.
- (IBAction)showHour:(id)sender
{
[self.hourButtons enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
UIButton *button = (UIButton *)obj;
// Grab the mutable string from the button and make a mutable copy
NSMutableAttributedString *attributedText = [[button attributedTitleForState:UIControlStateNormal] mutableCopy];
// Shared attribute styles
UIFont *btnFont = [UIFont fontWithName:#"Metric-Semibold" size:14.0];
NSNumber *btnTracking = [NSNumber numberWithFloat:0.25];
NSMutableParagraphStyle *btnStyle = [[NSMutableParagraphStyle alloc] init];
[btnStyle setLineSpacing:2.0];
// Since we can't set a color directly on a Attributed string we have
// to make a new attributed string.
if (button != sender && button.enabled) {
// Return to the default color
UIColor *btnTextColor = [UIColor colorWithRed:(147/255.0f) green:(147/255.0f) blue:(147/255.0f) alpha:1.0];
// Set up attributes
NSDictionary *btnAttrs = [NSDictionary dictionaryWithObjectsAndKeys:
btnFont, NSFontAttributeName,
btnTextColor, NSForegroundColorAttributeName,
btnTracking, NSKernAttributeName, nil];
// Reapply the default color (for the one button that was changed to white)
[attributedText setAttributes:btnAttrs
range:NSMakeRange(0, attributedText.length)];
// Add line-height
[attributedText addAttribute:NSParagraphStyleAttributeName
value:btnStyle
range:NSMakeRange(0, attributedText.length)];
// Reset default attributes
[button setBackgroundColor:[UIColor clearColor]];
[button setAttributedTitle:attributedText forState:UIControlStateNormal];
}
else {
// Our new white color for the active button
UIColor *btnTextColor = [UIColor whiteColor];
// Set up attributes
NSDictionary *btnAttrs = [NSDictionary dictionaryWithObjectsAndKeys:
btnFont, NSFontAttributeName,
btnTextColor, NSForegroundColorAttributeName,
btnTracking, NSKernAttributeName, nil];
// Apply our new white color
[attributedText setAttributes:btnAttrs
range:NSMakeRange(0, attributedText.length)];
// Add line-height
[attributedText addAttribute:NSParagraphStyleAttributeName
value:btnStyle
range:NSMakeRange(0, attributedText.length)];
// Add new attributes for active button
[button setBackgroundColor:[UIColor colorWithRed:(169/255.0f) green:(234/255.0f) blue:(255/255.0f) alpha:1.0]];
[button setAttributedTitle:attributedText forState:UIControlStateNormal];
}
}];
[self displayHour:(long int)[sender tag]];
}
setTitleColor doesn't have any effect when the title is an attributed string. Either use a plain NSString or call setAttributedTitle again after applying the desired color to the attributed string.
Also it is very important not to have the button on System style, just put it on custom...
This is for similar questions, not for this particular question.
I created a custom class MyButton extended from UIButton. Then added this inside the Identity Inspector:
After this, change the button type to Custom:
Then you can set attributes like textColor and UIFont for your UIButton for the different states:
Then I also created two methods inside MyButton class which I have to call inside my code when I want a UIButton to be displayed as highlighted:
- (void)changeColorAsUnselection{
[self setTitleColor:[UIColor colorFromHexString:acColorGreyDark]
forState:UIControlStateNormal &
UIControlStateSelected &
UIControlStateHighlighted];
}
- (void)changeColorAsSelection{
[self setTitleColor:[UIColor colorFromHexString:acColorYellow]
forState:UIControlStateNormal &
UIControlStateHighlighted &
UIControlStateSelected];
}
You have to set the titleColor for normal, highlight and selected UIControlState because there can be more than one state at a time according to the documentation of UIControlState.
If you don't create these methods, the UIButton will display selection or highlighting but they won't stay in the UIColor you setup inside the UIInterface Builder because they are just available for a short display of a selection, not for displaying selection itself.
In my case, I am using XCode 7.x.
I faced up with the similar problem. After using NSAttributedString
let underlineAttribute = [NSUnderlineStyleAttributeName: NSUnderlineStyle.StyleSingle.rawValue]
let underlineAttributedString = NSAttributedString(string: "FILTER", attributes: underlineAttribute)
filterButton.setTitleColor(AppConfig.FOREGROUND, forState: .Normal)
filterButton.setAttributedTitle(underlineAttributedString, forState: .Normal)
the filterButton.setTitleColor(AppConfig.FOREGROUND, forState: .Normal) not get effected.
I change the Tint Color of the button in the Interface Builder (which is default as light blue). Now, it works for me now.
An alternative to the above answers is to apply the text colour using string attributes. You can set a different NSAttributedString for each control state, so this works to achieve the same effect - the button text will change colour on select/highlight.
Example:
// We're assuming attributedString already exists - this is your completed attributed string so far
// We're going to copy this string into two more NS(Mutable)AttributedString variables - one for the "normal" state and one for the "highlighted" state
NSMutableAttributedString *normalAttributedString = [[NSMutableAttributedString alloc] initWithAttributedString:attributedString];
// Set the desired foreground color (in this case it's for the "normal" state) for the length of the string
[normalAttributedString addAttribute:NSForegroundColorAttributeName value:[UIColor blackColor] range:NSMakeRange(0,attributedString.length)];
// Rinse and repeat for the highlighted state
NSMutableAttributedString *highlightedAttributedString = [[NSMutableAttributedString alloc] initWithAttributedString:attributedString];
[highlightedAttributedString addAttribute:NSForegroundColorAttributeName value:[UIColor blueColor] range:NSMakeRange(0,attributedString.length)];
// Finally, we'll set these as the attributedTitles for the relevant control states.
[myButton setAttributedTitle:normalAttributedString forState:UIControlStateNormal];
[myButton setAttributedTitle:highlightedAttributedString forState:UIControlStateSelected];
[myButton setAttributedTitle:highlightedAttributedString forState:UIControlStateHighlighted];
I noticed this immediately. Just a simple error probably :)
Change
UIColor *btnTextColor = [UIColor colorWithRed:(147/255.f)
green:(147/255.f)
blue:(147/255.f) alpha:1.0];
to
UIColor *btnTextColor = [UIColor colorWithRed:(147/255.0f)
green:(147/255.0f)
blue:(147/255.0f) alpha:1.0];
The reason it wasn't changing is probably because it wasn't recognizing the UIColor since you didn't have a full number in the division, since it was seeing (147/255.) instead of (147/255.0)

Resources