Letter spacing in iOS - ios

I have the following code:
[[cancelButton titleLabel] setFont:[UIFont fontWithName:#"ProximaNova-Regular" size:15]];
How would I set the letter-spacing as well?

You can't change the letter spacing in the abstract, which means that you can't change it at all under iOS 5 and below.
As of iOS 6, you can push an attributed string rather than a vanilla one to a UILabel. The process for pushing an attributed string works slightly differently from the process for pushing an ordinary one — the font, text colour and a bunch of other properties are all set on the string rather than on the label. The reason is that attributed strings allow different attributes to be set for different regions of the string. So you can set a string that combines multiple fonts, text colours, etc.
One of the supported Core Text attributes is kCTKernAttributeName, which as of iOS 6 is easier to take advantage of via the UIKit addition NSKernAttributeName. You can use kerning to adjust the horizontal spacing of glyphs.
Under iOS 5 and earlier you used to have to do a lot of mental jumping back and forth between Core Foundation C-style objects and Objective-C UIKit objects. As of 6 that's no longer necessary. But be wary if you search the 'net that things got a lot easier under 6 — if you see lots of __bridge casts and manual CFReleases then you're probably looking at older code.
Anyway, supposing you currently have something like:
UILabel *label = [cancelButton titleLabel];
UIFont *font = <whatever>;
UIColor *textColour = <whatever>;
NSString *string = <whatever>;
label.text = string;
label.font = font;
label.textColor = textColour;
You'd instead do something more like:
NSAttributedString *attributedString =
[[NSAttributedString alloc]
initWithString:string
attributes:
#{
NSFontAttributeName : font,
NSForegroundColorAttributeName : textColour
}];
label.attributedText = attributedString;
In your case, also to adjust the overall kerning you'd add:
NSAttributedString *attributedString =
[[NSAttributedString alloc]
initWithString:string
attributes:
#{
NSFontAttributeName : font,
NSForegroundColorAttributeName : textColour,
NSKernAttributeName : #(-1.3f)
}];
label.attributedText = attributedString;
Or whatever kerning value you want to apply. See the various constants at the bottom of the NSAttributedString UIKit Additions Reference for the various other attributes you can apply and which version of iOS they first became available on.
Much later addendum: while still being one of the least Swifty people you'll meet, I think this is the equivalent in Swift:
button.titleLabel?.attributedText =
NSAttributedString(
string: string,
attributes:
[
NSFontAttributeName: font,
NSForegroundColorAttributeName: textColour,
NSKernAttributeName: -1.3
])

NSAttributedString *cancelButtonAttributedString = [[NSAttributedString alloc]
initWithString:#"Hello"
attributes:
#{
NSKernAttributeName: #(1.5)
}];
[cancelButton setAttributedTitle:cancelButtonAttributedString forState:UIControlStateNormal];
This is only simple answer for above question

One of the supported Core Text attributes is kCTKernAttributeName, which as of iOS 6 is easier to take advantage of via the UIKit addition NSKernAttributeName. You can use kerning to adjust the horizontal spacing of glyphs.
Kerning is the adjustment of space between two unique letters. Kerning varies between different character pairs. For example, a combination like 'AVA' would have a different kerning between characters than something like 'VVV'
By using NSKernAttributeName, you're actually overriding that custom space adjustment that is built into the font file, setting all the various character pair kern values to the same number, thus breaking the optimal kerning. When applied to an entire string of text, small amounts of kerning the broken spacing is more noticeable. However, high kerning values could push the letter far enough apart to the point that the poor spacing will not be as noticeable.
What you're looking for is Tracking (aka letter spacing), which is the spacing between all the letters in a given block of text. Unfortunately, iOS does not seem to let you control that attribute.

Related

IOS Objective C UILabel font size is keeping its storyboard setting

I am using objectiveC for an old project and I am setting the label font size programmatically like this :
UIFont *font = [self fontToFitHeight:NSLocalizedString(#"#61_NEW_FINAL", nil) font:self.rulesLabel.font size:self.rulesLabel.frame.size.height];
[self.rulesLabel setFont:font];
NSLog(#"after call : fontszie is : %lf",self.rulesLabel.font.pointSize);
I can include the helper function if needed, but it returns me what I want, which is a font with fontsize around 5, which i see printed.
But when running that my font size is definitely not 5, but instead whatever value I have in the Storyboard settings (in my case 16). Above code is called inside viewDidLoad.
What am I missing?
NSAttributedString can include one or more fonts, perhaps this is your issue. If you have set the text of the label to be an attributed string that contains a font or a color, changing the base font or color of the label will not make a difference. In order for it to work as expected, you can either remove any font formatting of your attributed string (that I assume that you set through IB) or recreate the string in code and add the proper font to it, like so:
NSString *text = NSLocalizedString(#"#61_NEW_FINAL", #"Don't leave this out");
UIFont *font = [self fontToFitHeight:text font:self.rulesLabel.font size:self.rulesLabel.frame.size.height];
NSMutableAttributedString *labelAttributes = [[NSMutableAttributedString alloc] initWithString:text];
[labelAttributes addAttribute:NSFontAttributeName
value:font
range:NSMakeRange(0, labelAttributes.length)];
At this point, changing the font of the label will make absolutely no difference to its apperance, since the entire text has a predefined font already.

is there any way to make TextFlied input like google wallet input in ios ? please see attached photo for your understanding what i need

I want same textfield or any control in iOS Objective-C, like this image
google wallet input entry.
Yes totally possible Use NSAttributed String here is the link NSAttributedString
Create 2 NSDictionary one for smaller fontSize and one for Bigger fontSize.
in the small font size Attributed Dictionary the size for the NSBaselineOffsetAttributeName is used to move the small font up or down change the value to see the effect.
// I have added the attribute for font color as well so it should look the same as picture above
NSDictionary *smallFontSize = #{
NSFontAttributeName : [UIFont systemFontOfSize:10],
NSBaselineOffsetAttributeName : [[NSNumber alloc] initWithInt:10],
NSForegroundColorAttributeName : [UIColor grayColor]
};
Second dictionary is very simple it only contains the font Size
NSDictionary *bigFontSize = #{
NSFontAttributeName : [UIFont systemFontOfSize:25]
};
Declare NSMutableAttributedString not AttributedString pass in the samllFontSize
// I have directly passed the $ sign but you will pass it as a property
NSMutableAttributedString *mutableAttriString = [[NSMutableAttributedString alloc] initWithString:#"$" attributes:smallFontSize];
Now create two new AttributedStrings these 2 can be attributedString because we are not manipulating them
// You will be passing the amount and decimals as properties
NSAttributedString *amount = [[NSAttributedString alloc] initWithString:#"10" attributes:bigFontSize];
NSAttributedString *decimalAmount = [[NSAttributedString alloc] initWithString:#"00" attributes:smallFontSize];
Now try to append both amount and decimalAmount to the mutableAttributedString that was the reason we made the first one mutable so we can append to it later
[mutableAttriString appendAttributedString:amount];
[mutableAttriString appendAttributedString:decimalAmount];
Each label has a property called text and another one called attributedText add it to the attributedText property
self.priceLabel.attributedText = mutableAttriString
Here is the screenshot of the label change the font and colours to your liking.

Scaling NSAttributedString with Size Classes in iOS

I'm using NSAttributedString to make a section of a UILabel bold, and I've been looking at how I might scale the font across different size classes.
The only way I can currently see to do this is to use the existing font size of the label when adding the attribute:
CGFloat fontSize = self.label.font.pointSize;
NSMutableAttributedString * string = [[NSMutableAttributedString alloc] initWithString:#"Abc Abc"];
[string addAttribute:NSFontAttributeName
value:[UIFont boldSystemFontOfSize:fontSize]
range:NSMakeRange(0,3)];
self.label.attributedText = string;
To clarify: label is a UILabel with a regular system font, and the attributed string is used to make the first 3 letters bold.
This works reasonably well, but couples the creation of the attributed string with the label. Is there a way to scale the attributed string without knowing the font size up front?
After discussion with #Larcerax, I found that I could use the Autoshrink property on my UILabel in Interface Builder to ensure the font scales down appropriately, which gives the (somewhat dirty) solution of using an obscenely large maximum font size which can be scaled down:
NSMutableAttributedString * string = [[NSMutableAttributedString alloc] initWithString:#"Abc Abc"];
[string addAttribute:NSFontAttributeName
value:[UIFont boldSystemFontOfSize:200.0]
range:NSMakeRange(0,3)];
self.label.attributedText = string;
This does require deciding upon a maximum size ahead of time, though.

Set AutoLayout constraints to align multiline label

I'm new to iOS and AutoLayout.
In one of my table views I have cells that contain 2 labels (let's say title and subtitle)
Title can be quite long so I want it to expand to 2 rows if needed.
Subtitle always have 1 line.
I've made some screens to present the problem (I attached links because I don't have enough reputation points)
Let's the first photo be the start point.
I would like to have constant 8px space between labels and also (here is where problem starts) I need them to be centered verticaly (space between title and superview.top should be equal to space between subtitle and superview.bottom)
I'm able to this but only if title label have 1 line.
What constraints are needed to get it look like on photo 2?
At this moment I have pinned them like so:
8px between title and subtitle (varticaly) - priority 1000
16px between title and superview.top - priority 750
16px between subtitle and superview.bottom - priority 750
But it doesn't work.
PS. I have set number of lines to 0.
Thanks for any help.
UITableViewCellStyleSubtitle has built-in support for self-sizing.
It will support an image, multi-line title, and a subtitle, without you needing to write or maintain any custom code to handle what it can already do.
Update:
Here is an example of using attributed text to take the place of 4 different "labels" for a subtitle:
In tableView:cellForIndexPath:
cell.detailTextLabel.attributedText = [self attributedTextForBookSources:sourcesValue];
Helper methods:
/**
The attributed text string corresponding to the referenced gospel books
#param sourcesValue An integer number representing a bitfield of gospel books that have source details for a pericope
#return The attributed string identifying the gospel book sources
*/
- (NSAttributedString *)attributedTextForBookSources:(NSInteger)sourcesValue
{
UIFont *font = [UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline];
UIColor *textcolor = [self textColorForPericopeSource:sourcesValue & CGIPericopeSourcesMatt];
NSMutableAttributedString *books = [[NSMutableAttributedString alloc] initWithString:#"Matt " attributes:#{NSFontAttributeName : font, NSForegroundColorAttributeName : textcolor}];
textcolor = [self textColorForPericopeSource:sourcesValue & CGIPericopeSourcesMark];
[books appendAttributedString:[[NSAttributedString alloc] initWithString:#" Mark " attributes:#{NSFontAttributeName : font, NSForegroundColorAttributeName : textcolor}]];
textcolor = [self textColorForPericopeSource:sourcesValue & CGIPericopeSourcesLuke];
[books appendAttributedString:[[NSAttributedString alloc] initWithString:#" Luke " attributes:#{NSFontAttributeName : font, NSForegroundColorAttributeName : textcolor}]];
textcolor = [self textColorForPericopeSource:sourcesValue & CGIPericopeSourcesJohn];
[books appendAttributedString:[[NSAttributedString alloc] initWithString:#" John" attributes:#{NSFontAttributeName : font, NSForegroundColorAttributeName : textcolor}]];
return [[NSAttributedString alloc] initWithAttributedString:books];
}
- (UIColor *)textColorForPericopeSource:(BOOL)included
{
return included ? [UIColor darkGrayColor] : [UIColor clearColor];
}
My code just hides or shows a book, but you may be able to also use an attributed string based on your four labels.
Anytime you can use the built-in styles, it generally means less code for you to write, maintain, and support, down the road, and more likelihood of it still working in a future version of iOS.
That app's cell self-sizes itself, and you see it can handle a multi-line title as you need.

Text Formatting Using UITextView

I have a UITextView where user enter data. I have a format bar below which has
bold, italic, underline and other options like alignment etc.
After a lot of search and testing I came to know that NSString don't support such bold, italic styling instead NSAttributedString should be used but I use NSAttributedString I am unable to make the selected text bold and italic at the same time.
My code is like this
NSMutableAttributedString *textViewText = [[NSMutableAttributedString alloc]initWithAttributedString:textView.attributedText];
NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:text];
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
if(textBoldBtn){
UIFont *boldFont = [UIFont boldSystemFontOfSize:textView.font.pointSize];
NSDictionary *boldAttr = [NSDictionary dictionaryWithObject:boldFont forKey:NSFontAttributeName];
[dict addEntriesFromDictionary:boldAttr];
}
if(textItalicBtn){
UIFont *italicFont = [UIFont italicSystemFontOfSize:textView.font.pointSize];
NSDictionary *italicAttr = [NSDictionary dictionaryWithObject:italicFont forKey:NSFontAttributeName];
[dict addEntriesFromDictionary:italicAttr];
}
attributedText = [[NSMutableAttributedString alloc] initWithString:text attributes:dict];
[textViewText appendAttributedString:attributedText];
textView.attributedText = textViewText;
return true;
}
Using this technique it only takes the last font in dict when both buttons are pressed.
I have gone through a link on stack overflow where they use fontDescriptor of Label to make the text both italic and bold but note I don't want to use any label. I am using UITextView. I have also gone through
[textView setAllowsEditingTextAttributes:YES];
But I want my own functions. I have also seen several EGOTextView and TextEdit for iOS but I strictly want this for iPad. I only want to use UITextView.
Kindly tell if there is any way using attributed string to make text both italic bold and even underline at the same time or any way to customize the functions of textView personal EditingTextAttributes functionality.
Thanks in Advance.
*App has to be uploaded to app store so no private frameworks required because they would cause rejection of app.
You have a some issues.
First:
Attributes are a NSDictionary. That means works with key/value, and the key is unique!
So when, you use addEntriesFromDictionary:, the doc says:
If both dictionaries contain the same key, the receiving dictionary’s
previous value object for that key is sent a release message, and the
new value object takes its place.
And when you want to apply bold and italic effect in your code, you think that you have:
Key — Value
NSFontAttributeName — theBoldFont
NSFontAttributeName — theItalicFont
Whereas you replace the bold font with the italic one.
Second:
Since Bold AND Italic are a attribute "hidden" in UIFont, if you want to apply the both effect, you have to find a font which is italic AND bold. That why, underlining (NSUnderlineAttributeName) can be added without encountering your issue with bold and italic.
You may look there to know how to do about it.
So you may code some logic like this:
if (textItalicBtn && textBoldBtn)
{}
else if (textItalicBtn)
{}
else if (textBoldBtn)
{}

Resources