Set AutoLayout constraints to align multiline label - ios

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.

Related

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.

CoreText Attributed String Height Calculation Inaccurate

CoreText isn't giving the correct height of the attributed string (its short by a line or more). I have seen a lot of posts on SO about this but unable to understand or find a solution. Can somebody explain how Core Text height calculation works? Here's an example code I wrote showing inaccurate height calculation.
Context
I have a collection view where the cell's height is determined by the content inside it.
I am displaying paragraphs of text in the cells. I would like to save some performance by doing the height calculation using core text. I have seen that with core text's height calculation I could save ~300ms.
Code
// Height Calculation
+ (CGFloat)getHeight
{
NSString *text = #"The Apple HIG recommends to use a common color for links and buttons and we did just that. By using the same color throughout the app we trained the user to always associate blue to a link.The Apple HIG recommends to use a common color for links and buttons and we did just that.By using the same color throughout the app we trained the user to always associate blue to a link.";
NSAttributedString *attrStr = [self attributedString:text withLinespacing:3 withLineBreakMode:NSLineBreakByWordWrapping];
CTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)(attrStr));
CGSize suggestedSize = CTFramesetterSuggestFrameSizeWithConstraints(frameSetter,
CFRangeMake(0, attrStr.length),
NULL,
CGSizeMake(320, 9999),
NULL);
return suggestedSize.height;
}
// Load the same text when Cell is about to display
- (void)loadData
{
NSString *text = #"The Apple HIG recommends to use a common color for links and buttons and we did just that.By using the same color throughout the app we trained the user to always associate blue to a link.The Apple HIG recommends to use a common color for links and buttons and we did just that.By using the same color throughout the app we trained the user to always associate blue to a link.";
NSAttributedString *attrStr = [[self class] attributedString:text withLinespacing:3 withLineBreakMode:NSLineBreakByWordWrapping];
// UILabel element
self.textLabel.attributedText = attrStr;
self.layer.borderColor = [UIColor blueColor].CGColor;
self.layer.borderWidth = 1.0f;
}
// Generate attributed string with leading, font and linebreak
+ (NSAttributedString *)attributedString:(NSString *)string
withLinespacing:(CGFloat)linespacing
withLineBreakMode:(NSLineBreakMode)lineBreakMode
{
NSMutableAttributedString *attrStr = [[NSMutableAttributedString alloc] initWithString:string];
NSInteger strLength = [string length];
NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
style.lineSpacing = linespacing;
style.lineBreakMode = lineBreakMode;
[attrStr addAttributes:#{NSParagraphStyleAttributeName: style,
NSFontAttributeName: [UIFont fontWithName:#"HelveticaNeue" size:15]} range:NSMakeRange(0, strLength)];
return attrStr;
}
The above code uses core text to calculate the height and UILabel to display the text. The UILabel has 3 constraints to the cell {Top:17, Leading:13px, Trailing:13px}
CTFramesetterSuggestFrameSizeWithConstraints is known to be buggy, returning incorrect height values. The missing line bug you experience is very common, and there are no good solutions that I know of, only ugly workarounds which never give 100% accurate results.
For iOS7 and above, I recommend moving to TextKit. Somehow the calculations performed there internally do work correctly, while being based on Core Text also. Using NSLayoutManager's usedRectForTextContainer: returns a correct result.
You can see a more complete answer here. While not exactly 100% on topic, there is some discussion about the bugginess of Core Text calculations.

how to set a UITextView's text to be bolded and not clickable

I have the following HTML in a UITextView and would like to render it into a UITextView
is my body for the note
food item - more item stuff;`
Let me add: it's currently showing as blue and underlined and not clickable. I would like to make it bolded and not clickable. I have read the docs regarding linkTextAttributes but, not having used this, it is a bit beyond me and I don't really see any easy way to manipulate this. How would I just render the above link bolded and black (not blue) and maintain the non-clickable nature?
UPDATE (solution using UITextView's linkTextAttributes)
self.testTextView.editable = NO;
self.testTextView.selectable = YES;
self.testTextView.userInteractionEnabled = NO; // workaround to disable link - CAUTION: it also disables scrolling of UITextView content
self.testTextView.dataDetectorTypes = UIDataDetectorTypeLink;
self.testTextView.linkTextAttributes = #{NSFontAttributeName : [UIFont boldSystemFontOfSize:14.0f], // NOT WORKING !?
NSForegroundColorAttributeName : [UIColor redColor]};
...
self.testTextView.text = #"Lorem ipsum http://www.apple.com Lorem ipsum";
As you can see in comments, I wasn't able to set new font to linkTextAttributes, though the colour attribute was working as expected.
If you can get away with colour attribute or some other text attribute to style your URLs and you don't have to worry about disabled UITextView scrolling, then this may be your solution.
PREVIOUS (alternative solution)
If you're using Storyboard/xib then make sure you've deselected Detection -> Links for your UITextView. You can make your link bold by setting its container font to some bold typeface. If you want to support different text/font styles in one string object then you should really look for NSAttributedString or NSMutableAttributedString.
See: https://developer.apple.com/library/ios/documentation/cocoa/reference/foundation/classes/NSAttributedString_Class/Reference/Reference.html.
Example:
UIFont *linkFont = [UIFont fontWithName:#"SomeBoldTypeface" size:12];
NSString *link = #"food item - more item stuff";
NSMutableAttributedString *someString = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:#"is my body for the note %#; let me ad", link]];
[someString addAttribute:NSFontAttributeName value:linkFont range:NSMakeRange(24, link.length)];
UITextView *textView = [[UITextView alloc] init];
textView.attributedText = someString;
...

Letter spacing in 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.

text editing in text view xcode

I have a text view in which text is displayed like this:
how are you?
Fine
Now if i set font for text view, then the same font is displayed for the two lines(ques and answer), however i want question to be displayed in one font and answer in some other font. How can i do this?
I set font like this:
textView = [[UITextView alloc]initWithFrame:CGRectMake(10, 80, 300, 440)];
textView.layer.borderColor = [UIColor blackColor].CGColor;
[textView setFont:[UIFont fontWithName:#"TimesNewRomanPS-ItalicMT" size:14]];
textView.layer.borderWidth = 1.0;
textView.autoresizesSubviews = YES;
textView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self.view addSubview:textView];
Thanks in advance!!
From the UITextView class reference:
In iOS 6 and later, this class supports multiple text styles through
use of the attributedText property. (Styled text is not supported in
earlier versions of iOS.) Setting a value for this property causes the
text view to use the style information provided in the attributed
string. You can still use the font, textColor, and textAlignment
properties to set style attributes, but those properties apply to all
of the text in the text view.
This class does not support multiple styles for text. The font, color,
and text alignment attributes you specify always apply to the entire
contents of the text view. To display more complex styling in your
application, you need to use a UIWebView object and render your
content using HTML.
So you cannot have two on the same page for iOS 5 or less because it is not supported. Just use a webview and an HTML file. for iOS6 maybe you can try using attributedText property of UITextView. This is available under iOS 6. Never tried it though.
Or have 2 different UITextView's (its ugly but thats what it is).
I'm guessing you wanted to create a chatroom like app?
if so, I recommend make it a UITableView. And then make different Cells to match different styles.
You can use attributed strings to achieve this, for example:
NSMutableAttributedString *para1 = [[NSMutableAttributedString alloc] initWithString:#"How are you?"];
NSMutableAttributedString *para2 = [[NSMutableAttributedString alloc] initWithString:#"\nFine"];
[para2 setAttributes:#{ NSForegroundColorAttributeName : [UIColor blueColor]} range:NSMakeRange(0, para2.length)];
[para1 insertAttributedString:para2 atIndex:para1.length];
self.textLabel.attributedText = para1;
Or with a single attributed string:
NSMutableAttributedString *para1 = [[NSMutableAttributedString alloc] initWithString:#"How are you?\nFine"];
// Get the range of the last line in the string
__block NSRange range;
[para1.mutableString enumerateLinesUsingBlock:^(NSString *line, BOOL *stop) {
range = [para1.mutableString rangeOfString:line];
}];
[para1 setAttributes:#{ NSForegroundColorAttributeName : [UIColor blueColor] } range:range];
self.textLabel.attributedText = para1;
Both examples result in:

Resources