lineBreakMode for multiline attributed string - ios

I have a multiline label that will contain an attributed string. This is the code of the attributed string:
NSString * titleString = #"Title";
NSString * informationString = self.myObject.content;
NSString * allString = [NSString stringWithFormat:#"%#\n\n%#",titleString,informationString];
NSMutableAttributedString* attributedMessage = [[NSMutableAttributedString alloc]initWithString:allString];
NSMutableParagraphStyle* style=[[NSMutableParagraphStyle alloc]init];
style.alignment = NSTextAlignmentLeft;
NSDictionary *attributesTitle = [NSDictionary dictionaryWithObjectsAndKeys:style,NSParagraphStyleAttributeName,[UIColor blackColor],NSForegroundColorAttributeName,[UIColor clearColor],NSBackgroundColorAttributeName,Font(#"OpenSans-Semibold", 17+(int)((self.view.bounds.size.width-290.)/15.)),NSFontAttributeName,nil];
NSMutableParagraphStyle* styleText=[[NSMutableParagraphStyle alloc]init];
styleText.alignment = NSTextAlignmentLeft;
styleText.lineBreakMode = NSLineBreakByTruncatingTail;
NSDictionary *attributesInformation = [NSDictionary dictionaryWithObjectsAndKeys:styleText,NSParagraphStyleAttributeName,[UIColor colorWithRed:91./255 green:91./255 blue:91./255 alpha:1.],NSForegroundColorAttributeName,[UIColor clearColor],NSBackgroundColorAttributeName,[UIFont fontWithName:#"Roboto-Light" size:13.+(int)((self.view.bounds.size.width-290.)/15.)],NSFontAttributeName,nil];
[attributedMessage setAttributes:attributesTitle range:[allString rangeOfString:titleString]];
[attributedMessage setAttributes:attributesInformation range:[allString rangeOfString:informationString]];
In my case the label is shown with ellipse "..." in all the lines. how can i resolve this issue. I want that will be shown only in the last visible line.

The solution that i adopted is
while (newHeight>=heightOfLabel){
remove some letter from the end of the string
calculate new height
}
replace the last three charachter with "..."
and it is done :)
I know that it is not a clean solution but it resolve my issue until finding a clean one.

Related

How to arrange NSString word in this type format without adding space in UILabel

I want to make this type format to word arrange in NSString on UILabel like
but I try to make add extra white space according to upper line word length but another way to make this type format suppose using NSAttributesString.
You can do this using NSMutableAttributedString without adding extra white space.
First, create a method that returns NSMutableAttributedString like this-
-(NSMutableAttributedString*)setIndent:(NSString*) title value:(CGFloat) value {
NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
style.alignment = NSTextAlignmentLeft;
style.firstLineHeadIndent = value;
NSMutableAttributedString *attrText = [[NSMutableAttributedString alloc] initWithString:title attributes:#{ NSParagraphStyleAttributeName : style}];
return attrText;
}
and use this method by the following way -
NSString *title = #"Charlie Chapline Cartoon";
NSArray* foo = [title componentsSeparatedByString: #" "];
NSMutableAttributedString *attrText5 = [[NSMutableAttributedString alloc] init];
CGFloat value = 0.0f;
for(int i = 0; i< foo.count; i++){
//change this value according to your need.
value = value + 20.0f;
[attrText5 appendAttributedString:[self setIndent:[NSString stringWithFormat:#"%#\n", foo[i]] value:value]];
}
_myLab.numberOfLines = 5;
_myLab.attributedText = attrText5;
Output:

Dynamic Number of UILabels in custom tableviewcell

I created a custom tableview cell and I want to display some strings in that cell. I fetch strings from backend thus I don't know how many labels I needed. I tried to concat strings in one label and implemented like below however I want to display strings with different attributes after char ":".
for (AttributesModel* attribute in model.attributes) {
NSString *attributeName = attribute.name;
attributeString = [[attributeString stringByAppendingString: attributeName] mutableCopy];
attributeString = [[attributeString stringByAppendingString: #" : "] mutableCopy];
for (NSDictionary *value in attribute.options) {
attributeString = [[attributeString stringByAppendingString: [value objectForKey:#"name"] ] mutableCopy];
attributeString = [[attributeString stringByAppendingString: #", "] mutableCopy];
}
attributeString = [[attributeString stringByAppendingString: #"\n"] mutableCopy];
}
I could not change attributes of strings thats located after char ":".
Are there any way to do that? Can I create dynamic number of labels in cell or only change attributes of strings that are only located after ":" ?
It sounds like you want to change the attributes such as formatting of a section of text within a UILabel. You can do this by:
Creating an attributed, mutable copy of your string (a.k.a converting an NSString into an NSMutableAttributedString).
Changing the attributes to parts of this copy.
Setting your label's attributedText property to your attributed string.
NSString *myString = #"This is my string";
NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:myString];
NSMutableAttributedString *mutableAttributedString = [attributedString mutableCopy];
// The range of text to change, i.e. start from the 5th index
// (starting from 0 like arrays), and continue for 2 characters:
NSRange rangeOfSecondWord = NSMakeRange(5, 2);
// The list of attributes to apply to that range:
NSDictionary *myAttributes = #{
NSForegroundColorAttributeName : [UIColor redColor],
};
// Actually apply the attributes:
[mutableAttributedString setAttributes:myAttributes range:rangeOfSecondWord];
// Set the text of the label to the attributed string:
myLabel.attributedText = mutableAttributedString;
For a list of attributes that you can set in your dictionary, see the Character Attributes reference.
Since you're downloading your strings, you may not know the range beforehand. Since you're concatenating them, here is how you can find the range dynamically:
NSString *stringOne = #"My name is ";
NSString *stringTwo = #"John Citizen";
NSString *joinedStrings = [stringOne stringByAppendingString:stringTwo];
NSRange rangeOfStringTwo = [joinedStrings rangeOfString:stringTwo];

Multiple text alignment with same label using NSMutableAttributedString on iOS

I want to set Text direction for my label using NSMutableAttributedString. for example, I have chat view, which contains message and time. I want to set left alignment for message and right alignment for time using UILabel.
I have used following code, but it's not working,
NSString *Time = [Functions stringFromGivenDate:msg.time withFormate:#"hh:mm a"];
NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:#"%#\n%#",msg.text,Time]];
NSDictionary *attrDictionary = #{NSWritingDirectionAttributeName:#[#(NSTextWritingDirectionOverride)]};
[str addAttributes:attrDictionary range:NSMakeRange(msg.text.length+1, Time.length)];
if I understood correctly, this should help:
NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
style.alignment = alignment;// type NSTextAlignment
NSDictionary *attributtes = #{NSParagraphStyleAttributeName : style,};

Replace the truncation ellipsis of UILabel in iOS 7

How can I replace the truncation ellipsis ("…") of a UILabel in iOS 7 with another attributed character? For example, with a colored ">".
I was hoping Text Kit's NSLayoutManager would make this possible, but it appears UILabel doesn't make it public if it uses it.
Also, can I safely assume that an ellipsis is used as the truncation character in every localisation? Maybe different languages have different truncation characters.
I recommend you use TTTAttributedLabel, just set property "attributedTruncationToken" to your custom string.
I don't think it gives you access to this. I think you would have do handle it manually. For example, use TextKit to determine the size of your string, if it doesn't fit in the available area, truncate it yourself and append a ">" and then put your new string in the label.
NSAttributedString has methods for getting the size of the string.
Let me know if you need any more detail on this..?
I think you can do some customization in -replaceElipsesForLabel method provided by Fonix to get your desired result.
I have written a method to do it, and works in iOS7
-(void)setCustomEllipsis:(NSString*)customEllipsis inLabel:(UILabel*)label with:(NSString*)string{
//Replace the ellipsis
NSMutableString* result = [[NSMutableString alloc] initWithString:#""];
NSArray* strings = [string componentsSeparatedByString:#" "];
for (NSString* s in strings) {
CGRect newSize = [[NSString stringWithFormat:#"%#%#%#",result,s,customEllipsis] boundingRectWithSize:CGSizeMake(label.frame.size.width,0) options:NSStringDrawingUsesLineFragmentOrigin attributes:#{NSFontAttributeName:label.font} context:nil];
if (newSize.size.height < label.frame.size.height) {
[result appendString:s];
[result appendString:#" "];
}else{
[result appendString:customEllipsis];
break;
}
}
[label setText:result];
//Set different font to the ellipsis
const CGFloat fontSize = 13;
UIFont *boldFont = [UIFont boldSystemFontOfSize:fontSize];
UIFont *regularFont = [UIFont systemFontOfSize:fontSize];
UIColor *foregroundColor = [UIColor lightGrayColor];
NSDictionary *attrs = [NSDictionary dictionaryWithObjectsAndKeys:regularFont, NSFontAttributeName,foregroundColor, NSForegroundColorAttributeName, nil];
NSDictionary *subAttrs = [NSDictionary dictionaryWithObjectsAndKeys:boldFont, NSFontAttributeName, nil];
const NSRange range = [label.text rangeOfString:customEllipsis];
NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:result
attributes:attrs];
[attributedText setAttributes:subAttrs range:range];
[label setAttributedText:attributedText];
}

Core Text in UITableviewCell's content overlapping and repeating and superimpose on the other cells

I am using Core Text to add text to UITableviewCell's content but arabic content seems to be overlapping and repeating itself as I scroll and superimpose on the other cells.
I am also using other elements on the page which appear just fine and are not repeating . Just the Core Text seems to be repeating.
I cant figure out why .
Here is my code:
- (CTFontRef)newCustomFontWithName:(NSString *)aFontName
ofType:(NSString *)type
attributes:(NSDictionary *)attributes {
NSString *fontPath = [[NSBundle mainBundle] pathForResource:aFontName ofType:type];
NSData *data = [[NSData alloc] initWithContentsOfFile:fontPath];
CGDataProviderRef fontProvider = CGDataProviderCreateWithCFData((__bridge CFDataRef)data);
CGFontRef cgFont = CGFontCreateWithDataProvider(fontProvider);
CGDataProviderRelease(fontProvider);
CTFontDescriptorRef fontDescriptor = CTFontDescriptorCreateWithAttributes((__bridge CFDictionaryRef)attributes);
CTFontRef font = CTFontCreateWithGraphicsFont(cgFont, 0, NULL, fontDescriptor);
CFRelease(fontDescriptor);
CGFontRelease(cgFont);
return font;
}
- (CATextLayer *)customCATextLayer:(NSString *)textString {
NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithFloat:24.f], (NSString *)kCTFontSizeAttribute,
[NSNumber numberWithInt:1], (NSString *)kCTLigatureAttributeName,
nil];
CTFontRef font = [self newCustomFontWithName:#"me_quranKer6"
ofType:#"ttf"
attributes:attributes];
CATextLayer *normalTextLayer = [[CATextLayer alloc] init];
normalTextLayer.font = font;
normalTextLayer.string = textString;
normalTextLayer.wrapped = YES;
normalTextLayer.foregroundColor = [[UIColor blackColor] CGColor];
normalTextLayer.fontSize = 24.f;
normalTextLayer.alignmentMode = kCAAlignmentCenter;
normalTextLayer.frame = CGRectMake(0.f, 10.f, 320.f, 32.f);
CFRelease(font);
return normalTextLayer;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
QuranVersesViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"verseCell"];
Verse *verse = [self.fetchedResultsController objectAtIndexPath:indexPath];
//English Content starts
NSMutableAttributedString * englishAttributedString;
if (!englishAttributedString)
englishAttributedString = [[NSMutableAttributedString alloc] initWithString:#""];
NSMutableAttributedString * englishSubtitleAttributedString;
NSMutableAttributedString * englishVerseAttributedString;
if (!englishVerseAttributedString)
englishVerseAttributedString = [[NSMutableAttributedString alloc] initWithString:verse.english_version];
NSMutableAttributedString * englishFootnoteAttributedString;
if (!englishFootnoteAttributedString)
englishFootnoteAttributedString = [[NSMutableAttributedString alloc] init];
NSString *englishString = #"";
if(verse.subtitle.length>0)
{
NSMutableParagraphStyle *mutParaStyle=[[NSMutableParagraphStyle alloc] init];
[mutParaStyle setAlignment:NSTextAlignmentCenter];
englishSubtitleAttributedString = [[NSMutableAttributedString alloc] initWithString:verse.subtitle];
[englishSubtitleAttributedString addAttributes:[NSDictionary dictionaryWithObject:mutParaStyle
forKey:NSParagraphStyleAttributeName]
range:NSMakeRange(0,[[englishSubtitleAttributedString string] length])];
[englishAttributedString appendAttributedString:englishSubtitleAttributedString];
[englishAttributedString addAttribute:NSFontAttributeName value:[UIFont fontWithName:#"Arial" size:30] range:NSRangeFromString(verse.subtitle)];
NSLog(#"text us %#", englishAttributedString);
}// englishString = [englishString stringByAppendingString:[NSString stringWithFormat:#"%#\n\n", verse.subtitle]];
[englishAttributedString appendAttributedString:englishVerseAttributedString];
englishString = [englishString stringByAppendingString:[NSString stringWithFormat:#"[%#:%#] %#\n", verse.whichSura.sura_no, verse.verse_no, verse.english_version]];
if(verse.footnote.length>0)
englishString = [englishString stringByAppendingString: [NSString stringWithFormat:#"\n%#\n", verse.footnote]];
englishString = [englishString stringByReplacingOccurrencesOfString:#"“" withString:#"\"" ];
englishString = [englishString stringByReplacingOccurrencesOfString:#"_" withString:#"\n" ];
cell.quranVerseEnglishTextView.attributedText = englishAttributedString;
[cell.quranVerseEnglishTextView autoResizeWithMaxWidth:MAX_TEXT_WIDTH];
cell.quranVerseEnglishTextView.backgroundColor = [UIColor clearColor];
//English Content starts
//Arabic Content
CATextLayer *arabicTextLayer = [self customCATextLayer:verse.arabic_version];
[cell.arabicView.layer addSublayer:arabicTextLayer];
return cell;
}
I was facing the same problem until I read up about NSAttributedStrings (made available in iOS 6) on this tutorial here.
The following code will solve your issue:
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:info.text attributes:#{ NSFontAttributeName : [UIFont fontWithName:#"Scheherazade" size:32], NSLigatureAttributeName: #2}];
cell.textLabel.attributedText = attributedString;
Out of curiosity, would I be correct to say that you opted to use CoreText because of difficulties in rendering embedded arabic fonts? I ventured the guess because I was attempting to use a similar method as you have done in your code when faced with that exact problem for a Quran app that I'm currently developing. If this so then I can confirm that using NSAttributedString also solves the problem. If you notice in the code above I've also set the NSLigatureAttributeName to 2 which according to the official Apple Class Reference Documentation means 'all ligatures'. Just note that this is something that I'm currently testing and I have yet to see the effects of this but I know that ligatures is a common problem in the rendering of some arabic fonts on certain platforms.
While on the subject, another common problem you may be facing is the line-spacing of arabic text and the slight overlapping of multi-line text and I've found that NSAttributedString can also be a good solution when used together with NSParagraphStyle (Hooray again for NSAttributedString!). Simply modify the above code as below:
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:info.text attributes:#{ NSFontAttributeName : [UIFont fontWithName:#"Scheherazade" size:32], NSLigatureAttributeName: #2}];
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
[paragraphStyle setLineSpacing:20];
[attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, [info.text length])];
cell.textLabel.attributedText = attributedString;
Hope this helps you or anyone else out there!
EDIT - Adding this helpful post on Common Mistakes With Adding Custom Fonts to Your iOS App for reference as a "checklist" when adding custom fonts on iOS.
Actually fixed the issue myself by adding the following line in cellforRowAtIndexPath:
if (cell == nil)
{
cell = [[QuranVersesViewCell alloc] init];
.....
and also did all the initialization and setting only when the cell was nil. And MOST importantly tagged the view layer and set the text for only the matching tagged view...

Resources