Scale UISegmentedControl labels based on width of control - ios

This seems like a no brainer, but I cannot find any way to do this. Basically what I have is a UISegmentedControl with two localized labels using NSLocalizedString. I have set the font size and everything looks great in English and a few other languages. But, in Japanese and other languages the characters are larger and cause the label to be truncated.
self.segmentedControl = [[UISegmentedControl alloc] initWithItems:
[NSArray arrayWithObjects:
NSLocalizedString(#"Miles", nil).uppercaseString,
NSLocalizedString(#"Kilometers", nil).uppercaseString,
nil]];
self.segmentedControl.apportionsSegmentWidthsByContent = YES;
self.segmentedControl.selectedSegmentIndex = self.metric ? 1 : 0;
[self.segmentedControl addTarget:self action:#selector(changeMetric:) forControlEvents:UIControlEventValueChanged];
self.segmentedControl.frame = CGRectMake(8, middleHolder.frame.size.height/2+60, progressWidth, 30);
self.segmentedControl.center = CGPointMake(self.view.center.x, self.segmentedControl.center.y);
[self.segmentedControl setTitleTextAttributes:#{
NSForegroundColorAttributeName: [UIColor whiteColor],
NSFontAttributeName: [UIFont fontWithName:#"HelveticaNeue-UltraLight" size:36]
} forState:UIControlStateSelected];
[self.segmentedControl setTitleTextAttributes:#{
NSForegroundColorAttributeName: [[UIColor whiteColor] colorWithAlphaComponent:0.3],
NSFontAttributeName: [UIFont fontWithName:#"HelveticaNeue-UltraLight" size:36]
} forState:UIControlStateNormal];
self.segmentedControl.tintColor = [UIColor clearColor];
self.segmentedControl.autoresizingMask = UIViewAutoresizingFlexibleWidth;
[middleHolder addSubview:self.segmentedControl];
Is there any way to scale the font size of the label depending on the label width? I realize that these are not normal UILabel's, so there is no adjustsFontSizeToFitWidth property.

I'm tackling with the same issue. Here is my solution (a bit rough around the edges):
I subclass the segmented control and then in my subclass, do the following. Hope this helps! (Tested on iOS 7 and 8)
+ (void)setSublabelScale:(UIView *)view {
for (id subview in view.subviews) {
if ([subview isKindOfClass:[UILabel class]]) {
[subview setMinimumScaleFactor:0.5];
[subview setAdjustsFontSizeToFitWidth:YES];
} else {
[MYSegmentedControl setSublabelScale:subview];
}
}
}
- (void)layoutSubviews {
[super layoutSubviews];
[MYSegmentedControl setSublabelScale:self];
}

I found out that NSAttributedString has a size property to it, that will allow me to know how wide the text is for every local. So, I can just do something like:
CGFloat fontSize = 36;
NSAttributedString* attributedString = [[NSAttributedString alloc] initWithString:NSLocalizedString(#"Kilometers", nil).uppercaseString attributes:#{NSFontAttributeName: [UIFont fontWithName:#"HelveticaNeue-UltraLight" size:fontSize]}];
if (attributedString.size.width > 200) {
fontSize = 30;
}

Related

How to resize text (font) to fit in UISegment of UISegmentedControl?

Is there any way to reduce font size that can be fit in single segment of UISegmentedControl ?
Have tried many thing something like,
[[UILabel appearanceWhenContainedIn:[UISegmentedControl class], nil] adjustsFontSizeToFitWidth];
[[UILabel appearanceWhenContainedIn:[UISegmentedControl class], nil] setMinimumScaleFactor:0.5];
AND
NSArray *arr = segment.subviews; // segment is UISegmentedControl object
for (int i = 0; i < arr.count; i++) {
UIView *aSegment = [arr objectAtIndex:i];
for (UILabel *label in aSegment.subviews) {
if ([label isKindOfClass:[UILabel class]]) {
UILabel *myLabel = (UILabel *)label;
[myLabel setNumberOfLines:0];
label.numberOfLines = 0;
label.adjustsFontSizeToFitWidth = YES;
label.minimumScaleFactor = 0.5;
}
}
}
able to set number of lines of label of segment like,
[[UILabel appearanceWhenContainedIn:[UISegmentedControl class], nil] setNumberOfLines:0];
Can set single segment size as per content like,
segment.apportionsSegmentWidthsByContent = YES;
but every segment has different size in this case.
I want to keep same size of every segment and want to reduce font size that can be fit in UISegmentLabel (label) of UISegmentedControl something like minimumscalefactor or minimumfontsize or adjustsFontSizeToFitWidth. These properties is not working for label when contains in UISegmentedControl.
If any one can help to achieve this, it will be appreciated!!
Thanks in advance!!
I found the issue, Actually it was my mistake!!! I was setting numberOfLines,adjustsFontSizeToFitWidth,minimumScaleFactor and TitleTextAttributes toghether. If we set titleTextAttribute then minimumScaleFactor can't work.
Update : (As asked by #HawkEye1194 in comment of another answer)
I have end up with below solution,
//this will allow multiple lines in label contained by every segment in segmentedcontroller
[[UILabel appearanceWhenContainedIn:[UISegmentedControl class], nil] setNumberOfLines:0];
UISegmentedControl *segment = [[UISegmentedControl alloc]initWithItems:option];
segment.frame = CGRectMake(20, 50, self.view.frame.size.width - 40, 50);
segment.tintColor = [UIColor grayColor];
segment.selectedSegmentIndex = 0;
segment.backgroundColor = [UIColor whiteColor];
segment.tag = segmentedControllerBaseTag;
[segment addTarget:self action:#selector(segmentChanged:) forControlEvents:UIControlEventValueChanged];
[segment setTitleTextAttributes:#{NSFontAttributeName :[UIFont fontWithName:#"HelveticaNeue" size:17.0], NSForegroundColorAttributeName : [UIColor darkGrayColor] } forState:UIControlStateNormal];
[segment setTitleTextAttributes:#{NSFontAttributeName : [UIFont fontWithName:#"HelveticaNeue" size:17.0],NSForegroundColorAttributeName : [UIColor whiteColor]} forState:UIControlStateSelected];
If your not setting title textattribute as above then you can use below code
// ********** if titletextattributes are not set then below method works ***********
for(uint i=0;i<[segment subviews].count;i++)
{
for(UIView *view in [[[segment subviews] objectAtIndex:i] subviews])
{
if([view isKindOfClass:[UILabel class]])
{
[(UILabel*)view setNumberOfLines:0];
[(UILabel*)view setAdjustsFontSizeToFitWidth:YES];
[(UILabel*)view setMinimumScaleFactor:0.7];
}
}
}
You can adjust single segment's size as per it's content by below code,
//*************** adjust single segment size as per content
segment.apportionsSegmentWidthsByContent = YES;
Try this, I hope this will help you and you will get an idea how this works-
I have a UISegmentedControl i.e. _userProfileSagmentOutlet having three segments. Here is sample code-
CGFloat fontSize = 15;
[_userProfileSagmentOutlet setTitleTextAttributes:#{NSFontAttributeName:[UIFont fontWithName:#"Roboto-medium" size:fontSize],
NSForegroundColorAttributeName:[UIColor whiteColor]}
forState:UIControlStateSelected];
[_userProfileSagmentOutlet setTitleTextAttributes:#{NSFontAttributeName:[UIFont fontWithName:#"Roboto-medium" size:fontSize],
NSForegroundColorAttributeName:[UIColor whiteColor]}
forState:UIControlStateNormal];
this is the previous code which truncate tail of title like below image-
here is the main logic which fit each title in segments with same font size-
CGFloat fontSize = 15;
NSAttributedString* firstTitle = [[NSAttributedString alloc] initWithString:#"Membership History" attributes:#{NSFontAttributeName: [UIFont fontWithName:#"Roboto-medium" size:fontSize]}];
NSAttributedString* secondTitle = [[NSAttributedString alloc] initWithString:#"Event History" attributes:#{NSFontAttributeName: [UIFont fontWithName:#"Roboto-medium" size:fontSize]}];
NSAttributedString* thirdTitle = [[NSAttributedString alloc] initWithString:#"Booked Classes" attributes:#{NSFontAttributeName: [UIFont fontWithName:#"Roboto-medium" size:fontSize]}];
float maxW=MAX(MAX(firstTitle.size.width, secondTitle.size.width), thirdTitle.size.width);
while (maxW > _userProfileSagmentOutlet.subviews[0].frame.size.width) {
fontSize--;
firstTitle = [[NSAttributedString alloc] initWithString:#"Membership History" attributes:#{NSFontAttributeName: [UIFont fontWithName:#"Roboto-medium" size:fontSize]}];
secondTitle = [[NSAttributedString alloc] initWithString:#"Event History" attributes:#{NSFontAttributeName: [UIFont fontWithName:#"Roboto-medium" size:fontSize]}];
thirdTitle = [[NSAttributedString alloc] initWithString:#"Booked Classes" attributes:#{NSFontAttributeName: [UIFont fontWithName:#"Roboto-medium" size:fontSize]}];
maxW=MAX(MAX(firstTitle.size.width, secondTitle.size.width), thirdTitle.size.width);
}
[_userProfileSagmentOutlet setTitleTextAttributes:#{NSFontAttributeName:[UIFont fontWithName:#"Roboto-medium" size:fontSize],
NSForegroundColorAttributeName:[UIColor whiteColor]}
forState:UIControlStateSelected];
[_userProfileSagmentOutlet setTitleTextAttributes:#{NSFontAttributeName:[UIFont fontWithName:#"Roboto-medium" size:fontSize],
NSForegroundColorAttributeName:[UIColor whiteColor]}
forState:UIControlStateNormal];
after using this code image look like this(same font size and text fit to segment and works fine)-
Here is Swift extension if someone needed-
var fontSize:CGFloat = 15.0;
var firstTitle = NSMutableAttributedString.init(string: "Membership History", attributes:[NSFontAttributeName: UIFont.systemFontOfSize(fontSize)])
var secondTitle = NSMutableAttributedString.init(string: "Events History" ,attributes:[NSFontAttributeName: UIFont.systemFontOfSize(fontSize)]);
var thirdTitle = NSMutableAttributedString.init(string: "Booked Classes" ,attributes:[NSFontAttributeName: UIFont.systemFontOfSize(fontSize)]);
var maxW:CGFloat = max(max(firstTitle.size().width, secondTitle.size().width), thirdTitle.size().width);
while (maxW > userProfileSagmentOutlet.subviews[0].frame.size.width) {
fontSize--;
firstTitle = NSMutableAttributedString.init(string: "Membership History", attributes:[NSFontAttributeName: UIFont.systemFontOfSize(fontSize)])
secondTitle = NSMutableAttributedString.init(string: "Events History" ,attributes:[NSFontAttributeName: UIFont.systemFontOfSize(fontSize)]);
thirdTitle = NSMutableAttributedString.init(string: "Booked Classes" ,attributes:[NSFontAttributeName: UIFont.systemFontOfSize(fontSize)]);
maxW = max(max(firstTitle.size().width, secondTitle.size().width), thirdTitle.size().width);
}
userProfileSagmentOutlet.setTitleTextAttributes([NSFontAttributeName: UIFont.systemFontOfSize(fontSize),NSForegroundColorAttributeName:UIColor.whiteColor()], forState:UIControlState.Normal)
userProfileSagmentOutlet.setTitleTextAttributes([NSFontAttributeName: UIFont.systemFontOfSize(fontSize),NSForegroundColorAttributeName:UIColor.whiteColor()], forState:UIControlState.Selected)
SWIFT 4
allow multiple lines in label
if #available(iOS 9.0, *) {
UILabel.appearance(whenContainedInInstancesOf: [UISegmentedControl.self]).numberOfLines = 0
}
The most simple solution in modern Swift would be
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
_ = Your_UISegmentControl.subviews.compactMap { $0.subviews.compactMap {
($0 as? UILabel)?.adjustsFontSizeToFitWidth = true
($0 as? UILabel)?.minimumScaleFactor = 0.5
}}
}
I ran this in the view controller, and called it after viewDidAppear
func autoshrinkSegmentFontSize() {
for subview in segments.subviews {
for label in subview.subviews {
if let myLabel = subview as? UILabel {
myLabel.adjustsFontSizeToFitWidth = true
myLabel.minimumScaleFactor = 0.5
}
}
}
}

UITextField set placeholder color as dark in iOS

I have tried to set UITextField "Placeholder" color as dark.
NSAttributedString * search = [[NSAttributedString alloc] initWithString:#"Search" attributes:#{NSForegroundColorAttributeName: [UIColor blackColor]}];
textField.attributedPlaceholder = search;
But still UITextField showing light gray color in "Placeholder".
Is it possible to set dark "placeholder" color for UITextField?
Also I Have tried the another method as well
[textField setValue:[UIColor blackColor] forKeyPath:#"_placeholderLabel.textColor"];
But both methods are working in iOS 7, But not working on iOS 6.
Is it possible to set dark "placeholder" color for UITextField in iOS 6 target?
Thanks!
As suggested by Apple, subclassing UITextField and overriding - (void)drawPlaceholderInRect:(CGRect)rect is the way to go:
- (void)drawPlaceholderInRect:(CGRect)rect {
UIColor *colour = [UIColor lightGrayColor];
if ([self.placeholder respondsToSelector:#selector(drawInRect:withAttributes:)])
{ // iOS7 and later
NSDictionary *attributes = #{NSForegroundColorAttributeName: colour, NSFontAttributeName: self.font};
CGRect boundingRect = [self.placeholder boundingRectWithSize:rect.size options:0 attributes:attributes context:nil];
[self.placeholder drawAtPoint:CGPointMake(0, (rect.size.height/2)-boundingRect.size.height/2) withAttributes:attributes]; }
else { // iOS 6
[colour setFill];
[self.placeholder drawInRect:rect withFont:self.font lineBreakMode:NSLineBreakByTruncatingTail alignment:self.textAlignment];
}
}
Credit: http://www.brightec.co.uk/blog/how-change-colour-uitextfields-placeholder-text-ios7-and-still-support-ios6
Overriding the drawPlaceholderInRect: method to draw our own placeholder text.
- (void)drawPlaceholderInRect:(CGRect)rect
{
UIColor *colour = [UIColor darkColor];
if ([self.placeholder respondsToSelector:#selector(drawInRect:withAttributes:)]) {
// iOS7 and later
NSDictionary *attributes = #{NSForegroundColorAttributeName: colour, NSFontAttributeName: self.font};
CGRect boundingRect = [self.placeholder boundingRectWithSize:rect.size options:0 attributes:attributes context:nil];
[self.placeholder drawAtPoint:CGPointMake(0, (rect.size.height/2)-boundingRect.size.height/2) withAttributes:attributes];
}
else {
// iOS 6
[colour setFill];
[self.placeholder drawInRect:rect withFont:self.font lineBreakMode:NSLineBreakByTruncatingTail alignment:self.textAlignment];
}
}
OR
This case, likely crash if the internal variable changes in the future
Programmatically:
[self.MyTextField setValue:[UIColor blackColor] forKeyPath:#"_placeholderLabel.textColor"];
In UIStoryBoard:
OR
EDIT:
Playing with UITextFiled delegates. its like a tricky:
-(void)viewDidLoad{
self.mytxtField.text = #"PlaceholderText";
self.mytxtField.delegate = self;
self.mytxtField.textColor = [UIColor darkGrayColor];
}
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
if ([self.mytxtField.text isEqualToString: #"PlaceholderText"]) {
self.mytxtField.text = #"";
self.mytxtField.textColor = [UIColor blackColor];
}
}
-(void)textFieldDidEndEditing:(UITextField *)textField{
if ([self.mytxtField.text length]<1) {
self.mytxtField.text =#"PlaceholderText";
self.mytxtField.textColor = [UIColor darkGrayColor];
}
For iOS8, you can take advantage of #IBDesignable & #IBInspectable.
Here is a UITextField subclass in Swift which lets you set the placeholder color in Interface Builder and see the result instantly:
#IBDesignable class EDTextField: UITextField {
#IBInspectable var placeholderColor: UIColor = UIColor.whiteColor() {
didSet {
if let placeholder = self.placeholder {
let attributes = [NSForegroundColorAttributeName: placeholderColor]
attributedPlaceholder = NSAttributedString(string: placeholder, attributes: attributes)
}
}
}
}
Its very simple....
Try this to change placeholder text color..
UIColor *color = [UIColor blackColor];
textField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:placeholderText attributes:#{NSForegroundColorAttributeName: color}];
Here is Latest way to Change FONT and COLOR of placeholder text
self.emailField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:#"Email" attributes:#{NSForegroundColorAttributeName:[UIColor whiteColor],NSFontAttributeName :[UIFont fontWithName:#"OpenSans" size:14.0]}];
Try this
[textField setValue:[UIColor blackColor] forKeyPath:#"_placeholderLabel.textColor"];
To make it future-proof and completely customizable (color, font, size, etc.), I would just add a UILabel on top and hide/show it manually according to the UITextField contents.
Just make sure to set the label's userInteractionEnabled to NO.
It will change textField's palceholder textColor
[yourTextField setValue:[UIColor colorWithRed:150.0f/255.0f green:150.0f/255.0f blue:155.0f/255.0f alpha:1] forKeyPath:#"_placeholderLabel.textColor"];

Center vertically in UILabel with autoshrink

This is a little different from all the other "How do I center the text in a UILabel" questions here...
I have a UILabel with some text in it, I want to center the text vertically in the UILabel. What's the big deal, right? That's the default. The problem comes because my text is dynamic and I have autoshrink turn on. As the text grows larger, the font size shrinks. You get this behavior.
Notice that the font baseline has not moved, I want it to move so the numbers are centered vertically in the UILabel's frame.
Easy, right? I just remember the frame's original center in viewDidLoad
self.workoutTimeCenter = _workoutTimeLabel.center;
and then I call sizeToFit after I change the the text, right?
[_workoutTimeLabel sizeToFit];
_workoutTimeLabel.center = _workoutTimeCenter;
Well, sizeToFit did, I guess, exactly what it was supposed to do, resize the frame so the text fits without shrinking!
How can I vertically center the text in a UILabel while respecting baselines and autoshrink? (Note, an iOS5 and later solution is fine and I can even deal with an iOS6 and later solution.)
In my experience you can just set the -[UILabel baselineAdjustment] property to UIBaselineAdjustmentAlignCenters to achieve the effect you're describing.
From the docs:
baselineAdjustment
Controls how text baselines are adjusted when text
needs to shrink to fit in the label.
#property(nonatomic) UIBaselineAdjustment baselineAdjustment
Discussion
If the adjustsFontSizeToFitWidth property is set to YES,
this property controls the behavior of the text baselines in
situations where adjustment of the font size is required. The default
value of this property is UIBaselineAdjustmentAlignBaselines. This
property is effective only when the numberOfLines property is set to
1.
and
UIBaselineAdjustmentAlignCenters
Adjust text based relative to the center of its bounding box.
EDIT: adding a full view-controller that demonstrates this:
#interface TSViewController : UIViewController
#end
#implementation TSViewController
- (void) addLabelWithFrame: (CGRect) f baselineAdjustment: (UIBaselineAdjustment) bla
{
UILabel* label = [[UILabel alloc] initWithFrame: f];
label.baselineAdjustment = bla;
label.adjustsFontSizeToFitWidth = YES;
label.font = [UIFont fontWithName: #"Courier" size: 200];
label.text = #"00";
label.textAlignment = NSTextAlignmentCenter;
label.backgroundColor = [UIColor lightGrayColor];
label.userInteractionEnabled = YES;
[self.view addSubview: label];
UIView* centerline = [[UIView alloc] initWithFrame: CGRectMake(f.origin.x, f.origin.y+(f.size.height/2.0), f.size.width, 1)];
centerline.backgroundColor = [UIColor redColor];
[self.view addSubview: centerline];
UITapGestureRecognizer* tgr = [[UITapGestureRecognizer alloc] initWithTarget: self action: #selector(onTap:)];
[label addGestureRecognizer: tgr];
}
- (void) viewDidLoad
{
[super viewDidLoad];
[self addLabelWithFrame: CGRectMake(0, 0, 320, 200)
baselineAdjustment: UIBaselineAdjustmentAlignCenters];
[self addLabelWithFrame: CGRectMake(0, 220, 320, 200)
baselineAdjustment: UIBaselineAdjustmentAlignBaselines];
}
- (void) onTap: (UITapGestureRecognizer*) tgr
{
UILabel* label = (UILabel*)tgr.view;
NSString* t = [label.text stringByAppendingString: #":00"];
label.text = t;
}
#end
when working in IB, be sure to set align baselines to center
Note: line break CANNOT be word wrap for this to work, so it will NOT work multiline (good to set the line break to Truncate tail)
-(void)fitVerticallyToLabel:(UILabel *)lbl
{
CGFloat fontSize = lbl.frame.size.width / lbl.text.length;
[lbl setFont:[UIFont fontWithName:#"Helvetica-Bold" size:fontSize]];
CGRect rect = lbl.frame;
rect.origin.y += rect.size.height - fontSize;
rect.size.height = fontSize;
[lbl setFrame:rect];
}
How to Use: Call this method after setting the text to your label.
label.text = #"text";
[self fitVerticallyToLabel:label];
Note: I ahev taken UILabel from xib. You can take it programmatically too in that case you will have to set its text alignment NSTextAlignMentCenter
Try to implement this logic:
-(void)adjustLabel1Text1:(NSString *)text1
{
UILabel *lbl_first = [UIFont fontWithName:#"Helvetica" size:12];
text1 = [text1 stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
float hedingLblHeight = [self calculateHeightOfTextFromWidth:text1 : [UIFont fontWithName:#"Helvetica" size:12] :118 :UILineBreakModeWordWrap];
lbl_first.text=text1;
[lbl_first setFrame:CGRectMake(lbl_first.frame.origin.x, lbl_first.frame.origin.y, 118, hedingLblHeight)];
lbl_first.lineBreakMode = UILineBreakModeWordWrap;
lbl_first.numberOfLines = 0;
[lbl_first sizeToFit];
//////////Adjust the lable or any UIControl below this label accordingly.
float endResultHeight=[self calculateHeightOfTextFromWidth:text2 : [UIFont fontWithName:#"Helvetica" size:15] :299 :UILineBreakModeWordWrap];
if(hedingLblHeight>secondImgTitleHeight)
{
[lbl_endResult setFrame:CGRectMake(lbl_endResult.frame.origin.x, lbl_first.frame.origin.y+lbl_first.frame.size.height+5, 299, endResultHeight)];
}
else
{
[lbl_endResult setFrame:CGRectMake(lbl_endResult.frame.origin.x, lbl_first.frame.origin.y+lbl_first.frame.size.height+5, 299, endResultHeight)];
}
lbl_endResult.lineBreakMode=UILineBreakModeWordWrap;
lbl_endResult.numberOfLines = 0;
[lbl_endResult sizeToFit];
}
-(float) calculateHeightOfTextFromWidth:(NSString*)text : (UIFont*) withFont:(float)width :(UILineBreakMode)lineBreakMode
{
CGSize suggestedSize = [text sizeWithFont:withFont constrainedToSize:CGSizeMake(width, FLT_MAX) lineBreakMode:lineBreakMode];
return suggestedSize.height;
}
It has helped me a lot.Hope it works for you.
Try
yourLabel.textAlignment = UITextAlignmentCenter;

How can I set the font for the selected element in a UISegmentedControl?

I'm trying to use different fonts for the selected and un-selected segments in a UISegmentedControl. I can set the font for the normal segments, but I can't seem to set the font for the selected segment. Here's my code:
NSDictionary *attributes = [NSDictionary dictionaryWithObject:
[UIFont fontWithName:#"Verdana-Bold"
size:[UIFont buttonFontSize]]
forKey:UITextAttributeFont];
[playerNumber setTitleTextAttributes:attributes
forState:UIControlStateHighlighted];
If I change to UIControlStateNormal, all the segments are styled. However, I just want to style the highlighted/selected segment. (UIControlStateSelected doesn't work either.)
(There are a few similar StackOverflow questions, but I couldn't find an answer that solved my issue.)
What am I doing wrong or can't it be done at all?
Have you tried setting the font on segment select, rather than trying to predefine the selectedState font to be used for all segments? Something like the following (untested):
int segmentIndex = self.mySegmentedControl.selectedSegmentIndex;
if (segmentIndex == 0)
{
[self.mySegmentedControl setFont:[UIFont boldSystemFontOfSize:12] forSegmentAtIndex:0];
[self.mySegmentedControl setFont:[UIFont systemFontOfSize:10] forSegmentAtIndex:1];
}
else if (segmentIndex == 1)
{
[self.mySegmentedControl setFont:[UIFont systemFontOfSize:10] forSegmentAtIndex:0];
[self.mySegmentedControl setFont:[UIFont boldSystemFontOfSize:12] forSegmentAtIndex:1];
}
I do something along these lines in one of my apps now, but it is using images for the segments.
I met this issue today, I believe this is an iOS's bug.
Here is my hack.
#interface TFSegmentedControl : UISegmentedControl
#end
#import "TFSegmentedControl.h"
#implementation TFSegmentedControl
{
BOOL layoutedOnce;
}
- (void)updateSelectedStyle
{
for (UIView *view in self.subviews) {
BOOL selected = [[view valueForKey:#"selected"] boolValue];
for (UILabel *label in view.subviews) {
if ([label isKindOfClass:[UILabel class]]) {
UIFont *font = [self titleTextAttributesForState:UIControlStateNormal][UITextAttributeFont];
if (selected) {
UIFont *_font = [self titleTextAttributesForState:UIControlStateSelected][UITextAttributeFont];
if (_font) font = _font;
}
if (font != label.font) {
label.font = font;
CGRect frame = label.frame;
frame.size = [label.text sizeWithFont:font];
label.frame = frame;
}
}
}
}
}
- (void)sendActionsForControlEvents:(UIControlEvents)controlEvents
{
[self updateSelectedStyle];
[super sendActionsForControlEvents:controlEvents];
}
- (void)setSelectedSegmentIndex:(NSInteger)selectedSegmentIndex
{
[super setSelectedSegmentIndex:selectedSegmentIndex];
[self updateSelectedStyle];
}
- (void)layoutSubviews
{
[super layoutSubviews];
if (!layoutedOnce) {
layoutedOnce = YES;
[self updateSelectedStyle];
}
}
#end

iPhone Navigation Bar Title text color

It seems the iOS Navigation Bar title color is white by default. Is there a way to change it to a different color?
I am aware of the navigationItem.titleView approach using an image. Since my design skills are limited and I failed to get the standard glossy, I prefer changing the text color.
Any insight would be much appreciated.
Modern approach
The modern way, for the entire navigation controller… do this once, when your navigation controller's root view is loaded.
[self.navigationController.navigationBar setTitleTextAttributes:
#{NSForegroundColorAttributeName:[UIColor yellowColor]}];
However, this doesn't seem have an effect in subsequent views.
Classic approach
The old way, per view controller (these constants are for iOS 6, but if want to do it per view controller on iOS 7 appearance you'll want the same approach but with different constants):
You need to use a UILabel as the titleView of the navigationItem.
The label should:
Have a clear background color (label.backgroundColor = [UIColor clearColor]).
Use bold 20pt system font (label.font = [UIFont boldSystemFontOfSize: 20.0f]).
Have a shadow of black with 50% alpha (label.shadowColor = [UIColor colorWithWhite:0.0 alpha:0.5]).
You'll want to set the text alignment to centered as well (label.textAlignment = NSTextAlignmentCenter (UITextAlignmentCenter for older SDKs).
Set the label text color to be whatever custom color you'd like. You do want a color that doesn't cause the text to blend into shadow, which would be difficult to read.
I worked this out through trial and error, but the values I came up with are ultimately too simple for them not to be what Apple picked. :)
If you want to verify this, drop this code into initWithNibName:bundle: in PageThreeViewController.m of Apple's NavBar sample. This will replace the text with a yellow label. This should be indistinguishable from the original produced by Apple's code, except for the color.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
// this will appear as the title in the navigation bar
UILabel *label = [[[UILabel alloc] initWithFrame:CGRectZero] autorelease];
label.backgroundColor = [UIColor clearColor];
label.font = [UIFont boldSystemFontOfSize:20.0];
label.shadowColor = [UIColor colorWithWhite:0.0 alpha:0.5];
label.textAlignment = NSTextAlignmentCenter;
// ^-Use UITextAlignmentCenter for older SDKs.
label.textColor = [UIColor yellowColor]; // change this color
self.navigationItem.titleView = label;
label.text = NSLocalizedString(#"PageThreeTitle", #"");
[label sizeToFit];
}
return self;
}
Edit: Also, read Erik B's answer below. My code shows the effect, but his code offers a simpler way to drop this into place on an existing view controller.
I know this is a pretty old thread, but I think it would be useful to know for new users that iOS 5 brings a new property for establishing title properties.
You can use UINavigationBar's setTitleTextAttributes for setting the font, color, offset, and shadow color.
In addition you can set the same default UINavigationBar's Title Text Attributes for all the UINavigationBars throughout your application.
For example like so:
NSDictionary *navbarTitleTextAttributes = [NSDictionary dictionaryWithObjectsAndKeys:
[UIColor whiteColor],UITextAttributeTextColor,
[UIColor blackColor], UITextAttributeTextShadowColor,
[NSValue valueWithUIOffset:UIOffsetMake(-1, 0)], UITextAttributeTextShadowOffset, nil];
[[UINavigationBar appearance] setTitleTextAttributes:navbarTitleTextAttributes];
In iOS 5 you can change the navigationBar title color in this manner:
navigationController.navigationBar.titleTextAttributes = #{NSForegroundColorAttributeName: [UIColor yellowColor]};
Based on Steven Fisher's answer I wrote this piece of code:
- (void)setTitle:(NSString *)title
{
[super setTitle:title];
UILabel *titleView = (UILabel *)self.navigationItem.titleView;
if (!titleView) {
titleView = [[UILabel alloc] initWithFrame:CGRectZero];
titleView.backgroundColor = [UIColor clearColor];
titleView.font = [UIFont boldSystemFontOfSize:20.0];
titleView.shadowColor = [UIColor colorWithWhite:0.0 alpha:0.5];
titleView.textColor = [UIColor yellowColor]; // Change to desired color
self.navigationItem.titleView = titleView;
[titleView release];
}
titleView.text = title;
[titleView sizeToFit];
}
The advantage of this code, besides dealing with the frame properly, is that if you change the title of your controller the custom title view will also get updated. No need to update it manually.
Another big advantage is that it makes it really simple to enable custom title color. All you need to do is to add this method to the controller.
Most of the above suggestions are deprecated now, for iOS 7 use -
NSDictionary *textAttributes = [NSDictionary dictionaryWithObjectsAndKeys:
[UIColor whiteColor],NSForegroundColorAttributeName,
[UIColor whiteColor],NSBackgroundColorAttributeName,nil];
self.navigationController.navigationBar.titleTextAttributes = textAttributes;
self.title = #"Title of the Page";
Also, checkout the NSAttributedString.h for various text properties that could be set.
In IOS 7 and 8, you can change the Title's color to let's say green
self.navigationController.navigationBar.titleTextAttributes = [NSDictionary dictionaryWithObject:[UIColor greenColor] forKey:NSForegroundColorAttributeName];
To keep the question up-to-date, I'll add Alex R. R. solution, but in Swift:
self.navigationController.navigationBar.barTintColor = .blueColor()
self.navigationController.navigationBar.tintColor = .whiteColor()
self.navigationController.navigationBar.titleTextAttributes = [
NSForegroundColorAttributeName : UIColor.whiteColor()
]
Which results to:
Swift Version
I found most of you guys presented the answers of Objective_C version
I would like to implement this function by using Swift for anyone who needs it.
In ViewDidload
1.To make NavigationBar background becomes color (for example: BLUE)
self.navigationController?.navigationBar.barTintColor = UIColor.blueColor()
2.To make NavigationBar background becomes Image (for example : ABC.png)
let barMetrix = UIBarMetrics(rawValue: 0)!
self.navigationController?.navigationBar
.setBackgroundImage(UIImage(named: "ABC"), forBarMetrics: barMetrix)
3.To change NavigationBar title (for example :[Font:Futura,10] [Color:Red])
navigationController?.navigationBar.titleTextAttributes = [
NSForegroundColorAttributeName : UIColor.redColor(),
NSFontAttributeName : UIFont(name: "Futura", size: 10)!
]
(hint1: don't forget the "!" mark after the UIFont)
(hint2: there are lots of attributes of the title text, command click
the "NSFontAttributeName" you can enter the class and view keyNames
and the Objects types they required)
I hope I can help!:D
Method 1, set it in IB:
Method 2, one line of code:
navigationController?.navigationBar.barTintColor = UIColor.blackColor()
The solution by tewha works well if you are trying to change the color on a page, but I want to be able to change the color on every page. I made some small modifications so that it would work for all pages on a UINavigationController
NavigationDelegate.h
//This will change the color of the navigation bar
#import <Foundation/Foundation.h>
#interface NavigationDelegate : NSObject<UINavigationControllerDelegate> {
}
#end
NavigationDelegate.m
#import "NavigationDelegate.h"
#implementation NavigationDelegate
- (void)navigationController:(UINavigationController *)navigationController
willShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
CGRect frame = CGRectMake(0, 0, 200, 44);//TODO: Can we get the size of the text?
UILabel* label = [[[UILabel alloc] initWithFrame:frame] autorelease];
label.backgroundColor = [UIColor clearColor];
label.font = [UIFont boldSystemFontOfSize:20.0];
label.shadowColor = [UIColor colorWithWhite:0.0 alpha:0.5];
label.textAlignment = UITextAlignmentCenter;
label.textColor = [UIColor yellowColor];
//The two lines below are the only ones that have changed
label.text=viewController.title;
viewController.navigationItem.titleView = label;
}
#end
From iOS 5 onwards we have to set title text color and font of navigation bar using titleTextAttribute Dictionary(predefined dictionary in UInavigation controller class reference).
[[UINavigationBar appearance] setTitleTextAttributes:
[NSDictionary dictionaryWithObjectsAndKeys:
[UIColor blackColor],UITextAttributeTextColor,
[UIFont fontWithName:#"ArialMT" size:16.0], UITextAttributeFont,nil]];
Short and sweet.
[[[self navigationController] navigationBar] setTitleTextAttributes:#{NSForegroundColorAttributeName: [UIColor redColor]}];
Use the code below in any view controller viewDidLoad or viewWillAppear method.
- (void)viewDidLoad
{
[super viewDidLoad];
//I am using UIColor yellowColor for an example but you can use whatever color you like
self.navigationController.navigationBar.titleTextAttributes = #{NSForegroundColorAttributeName: [UIColor yellowColor]};
//change the title here to whatever you like
self.title = #"Home";
// Do any additional setup after loading the view.
}
This is my solution based upon Stevens
Only real difference is I put some handling in for adjust the position if depending on the text length, seems to be similar to how apple do it
UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(([self.title length] < 10 ? UITextAlignmentCenter : UITextAlignmentLeft), 0, 480,44)];
titleLabel.backgroundColor = [UIColor clearColor];
titleLabel.font = [UIFont boldSystemFontOfSize: 20.0f];
titleLabel.shadowColor = [UIColor colorWithWhite:0.0 alpha:0.5];
titleLabel.textAlignment = ([self.title length] < 10 ? UITextAlignmentCenter : UITextAlignmentLeft);
titleLabel.textColor = [UIColor redColor];
titleLabel.text = self.title;
self.navigationItem.titleView = titleLabel;
[titleLabel release];
You may want to adjust the 10 value depending on your font size
Swift 4 & 4.2 version:
self.navigationController.navigationBar.titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.green]
I ran into the problem with my nav buttons throwing the text out of center (when you only have one button). To fix that I just changed my frame size like so:
CGRect frame = CGRectMake(0, 0, [self.title sizeWithFont:[UIFont boldSystemFontOfSize:20.0]].width, 44);
I've customized the navigationBar's background image and left button item, and the gray title not fit the background. Then I use:
[self.navigationBar setTintColor:[UIColor darkGrayColor]];
to change the tint color to gray. And the title is white now! That's what I want.
Hope to help also :)
It's recommended to set self.title as this is used while pushing child navbars or showing title on tabbars.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// create and customize title view
self.title = NSLocalizedString(#"My Custom Title", #"");
UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
titleLabel.text = self.title;
titleLabel.font = [UIFont boldSystemFontOfSize:16];
titleLabel.backgroundColor = [UIColor clearColor];
titleLabel.textColor = [UIColor whiteColor];
[titleLabel sizeToFit];
self.navigationItem.titleView = titleLabel;
[titleLabel release];
}
}
This is a pretty old thread but I think of providing answer for setting Color, Size and Vertical Position of Navigation Bar Title for iOS 7 and above
For Color and Size
NSDictionary *titleAttributes =#{
NSFontAttributeName :[UIFont fontWithName:#"Helvetica-Bold" size:14.0],
NSForegroundColorAttributeName : [UIColor whiteColor]
};
For Vertical Position
[[UINavigationBar appearance] setTitleVerticalPositionAdjustment:-10.0 forBarMetrics:UIBarMetricsDefault];
Set Title and assign the attributes dictionary
[[self navigationItem] setTitle:#"CLUBHOUSE"];
self.navigationController.navigationBar.titleTextAttributes = titleAttributes;
This works for me in Swift:
navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName:UIColor.white]
self.navigationItem.title=#"Extras";
[self.navigationController.navigationBar setTitleTextAttributes: [NSDictionary dictionaryWithObjectsAndKeys:[UIFont fontWithName:#"HelveticaNeue" size:21], NSFontAttributeName,[UIColor whiteColor],UITextAttributeTextColor,nil]];
Use like this for Orientation support
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0,0,320,40)];
[view setBackgroundColor:[UIColor clearColor]];
[view setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight ];
UILabel *nameLabel = [[UILabel alloc] init];
[nameLabel setFrame:CGRectMake(0, 0, 320, 40)];
[nameLabel setBackgroundColor:[UIColor clearColor]];
[nameLabel setAutoresizingMask:UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin |UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin];
[nameLabel setTextColor:[UIColor whiteColor]];
[nameLabel setFont:[UIFont boldSystemFontOfSize:17]];
[nameLabel setText:titleString];
[nameLabel setTextAlignment:UITextAlignmentCenter];
[view addSubview:nameLabel];
[nameLabel release];
self.navigationItem.titleView = view;
[view release];
to set font size of title i have used following conditions.. maybe helpfull to anybody
if ([currentTitle length]>24) msize = 10.0f;
else if ([currentTitle length]>16) msize = 14.0f;
else if ([currentTitle length]>12) msize = 18.0f;
An update to Alex R. R.'s post using the new iOS 7 text attributes and modern objective c for less noise:
NSShadow *titleShadow = [[NSShadow alloc] init];
titleShadow.shadowColor = [UIColor blackColor];
titleShadow.shadowOffset = CGSizeMake(-1, 0);
NSDictionary *navbarTitleTextAttributes = #{NSForegroundColorAttributeName:[UIColor whiteColor],
NSShadowAttributeName:titleShadow};
[[UINavigationBar appearance] setTitleTextAttributes:navbarTitleTextAttributes];
I do believe proper way to set the colour of UINavigationBar is:
NSDictionary *attributes=[NSDictionary dictionaryWithObjectsAndKeys:[UIColor redColor],UITextAttributeTextColor, nil];
self.titleTextAttributes = attributes;
Code above is written is subclass on UINavigationBar, obviously works without subclassing as well.
This is one of those things that are missing. Your best bet is to create your own custom Navigation Bar, add a text box, and manipulate the color that way.
After encountering the same problem (as others) of the label that moves when we insert a button in the navBar (in my case i have a spinner that i replace with a button when the date is loaded), the above solutions didn't work for me, so here is what worked and kept the label at the same place all the time:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
// this will appear as the title in the navigation bar
//CGRect frame = CGRectMake(0, 0, [self.title sizeWithFont:[UIFont boldSystemFontOfSize:20.0]].width, 44);
CGRect frame = CGRectMake(0, 0, 180, 44);
UILabel *label = [[[UILabel alloc] initWithFrame:frame] autorelease];
label.backgroundColor = [UIColor clearColor];
label.font = [UIFont boldSystemFontOfSize:20.0];
label.shadowColor = [UIColor colorWithWhite:0.0 alpha:0.5];
label.textAlignment = UITextAlignmentCenter;
label.textColor = [UIColor yellowColor];
self.navigationItem.titleView = label;
label.text = NSLocalizedString(#"Latest Questions", #"");
[label sizeToFit];
}
return self;
You should call [label sizeToFit]; after setting the text to prevent strange offsets when the label is automatically repositioned in the title view when other buttons occupy the nav bar.
Can use this method in appdelegate file and can use at every view
+(UILabel *) navigationTitleLable:(NSString *)title
{
CGRect frame = CGRectMake(0, 0, 165, 44);
UILabel *label = [[[UILabel alloc] initWithFrame:frame] autorelease];
label.backgroundColor = [UIColor clearColor];
label.font = NAVIGATION_TITLE_LABLE_SIZE;
label.shadowColor = [UIColor whiteColor];
label.numberOfLines = 2;
label.lineBreakMode = UILineBreakModeTailTruncation;
label.textAlignment = UITextAlignmentCenter;
[label setShadowOffset:CGSizeMake(0,1)];
label.textColor = [UIColor colorWithRed:51/255.0 green:51/255.0 blue:51/255.0 alpha:1.0];
//label.text = NSLocalizedString(title, #"");
return label;
}
titleTextAttributes
Display attributes for the bar’s title text.
#property(nonatomic, copy) NSDictionary *titleTextAttributes
Discussion
You can specify the font, text color, text shadow color, and text shadow offset for the title in the text attributes dictionary, using the text attribute keys described in NSString UIKit Additions Reference.
Availability
Available in iOS 5.0 and later.
Declared In
UINavigationBar.h

Resources