emoji is clipped in UILabel in iOS - ios

Hello I'm working on chat app in which user can send smiley (emoji) to other user. For text its working perfect but when it contains emoji then it is correct. I have used method for this
- (CGSize)getSizeForText:(NSString *)text maxWidth:(CGFloat)width font:(NSString *)fontName fontSize:(float)fontSize {
CGSize constraintSize;
constraintSize.height = MAXFLOAT;
constraintSize.width = width;
NSDictionary *attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
[UIFont fontWithName:fontName size:fontSize], NSFontAttributeName,
nil];
CGRect frame = [text boundingRectWithSize:constraintSize
options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading)
attributes:attributesDictionary
context:nil];
CGSize stringSize = frame.size;
return stringSize;
}
and the results are something like
As from images you can see what i want to say and what i need. I need some between two lines when there is emoji text in UILabel. Any help will be appreciated. Thanks in advance.
Edit: I have given answer on this. But if some have some quick hack for this then that will be great for me.

I have made a good work to do it manually and it looks good for me now. I have added linespacing for label text and it works good for me. I have set text like
NSMutableAttributedString* attrString = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:#"%#",message_text]];
NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
[style setLineSpacing:4];
[attrString addAttribute:NSParagraphStyleAttributeName
value:style
range:NSMakeRange(0, [message_text length])];
lblChatMSG.attributedText = attrString;
and my method to get height of text is
- (CGSize)getSizeForText:(NSString *)text maxWidth:(CGFloat)width font:(NSString *)fontName fontSize:(float)fontSize {
CGSize constraintSize;
constraintSize.height = MAXFLOAT;
constraintSize.width = width;
NSMutableParagraphStyle * paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;
paragraphStyle.alignment = NSTextAlignmentLeft;
paragraphStyle.lineSpacing = 4;
NSDictionary *attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
[UIFont fontWithName:fontName size:fontSize], NSFontAttributeName,paragraphStyle,NSParagraphStyleAttributeName,
nil];
CGRect frame = [text boundingRectWithSize:constraintSize
options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading)
attributes:attributesDictionary
context:nil];
CGSize stringSize = frame.size;
return stringSize;
}
And the result is

I just increased the required height of the label and adjusted its origin.
// Expand label to avoid cutoff emojis
label.frame.size.height += 8.0
label.frame.origin.y -= 4.0

Related

Extra space at the end of UITextView

I added text in UITextView and to understand the boundaries I colored my UITextView with cyan color.
After google.com there is some extra space which I want to remove.
- (void)viewDidLoad {
[super viewDidLoad];
NSString *desc = [self htmlAfterReplacingTagsAndAddingStyle];
_descriptionTextView.attributedText = [[NSAttributedString alloc] initWithData: [desc dataUsingEncoding:NSUTF8StringEncoding] options: #{ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType } documentAttributes:nil error:nil];
_descriptionTextView.linkTextAttributes = #{ NSForegroundColorAttributeName: [UIColor blueColor], NSUnderlineStyleAttributeName: [NSNumber numberWithInt:NSUnderlineStyleSingle] };
_descriptionTextView.dataDetectorTypes = UIDataDetectorTypeLink;
_descriptionTextView.scrollEnabled = NO;
[self setTextViewHeight];
}
setTextViewHeight
- (void)setTextViewHeight {
UIFont *font = [UIFont fontWithName:#"OpenSans" size:14.0];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, _descriptionContainer.frame.size.width, CGFLOAT_MAX)];
label.numberOfLines = 0;
label.lineBreakMode = NSLineBreakByWordWrapping;
label.font = font;
NSString *desc = [self htmlAfterReplacingTagsAndAddingStyle];
label.attributedText = [[NSAttributedString alloc] initWithData: [desc dataUsingEncoding:NSUTF8StringEncoding] options: #{ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType } documentAttributes:nil error:nil];
[label sizeToFit];
_descriptionTextView.backgroundColor = UIColor.cyanColor;
[_descriptionTextView setContentInset:UIEdgeInsetsMake(0, 0, -80, 0)];
_descriptionContainerHeight.constant = label.frame.size.height;
}
I read about setting content inset but that is not helpful. Changing the value of -80 doesn't have any impact.
I would appreciate some pointers which can help me remove the extra space present at the bottom of uitextView.
Use
[_descriptionTextView setTextContainerInset:UIEdgeInsetsMake(0, 0, 0, 0)];
as can be readed in UITextView Class reference
textContainerInset Property The inset of the text container's layout
area within the text view's content area.
Declaration
OBJECTIVE-C
#property(nonatomic, assign) UIEdgeInsets
textContainerInset
Discussion
This property provides text margins for
text laid out in the text view. By default the value of this property
is (8, 0, 8, 0).
Hope this helps
You should be able to get somewhere with textContainerInset (see #ReinierMelian answer). There's also opportunity to vastly simplify the text height measurement...
UIFont *font = [UIFont fontWithName:#"OpenSans" size:14.0];
CGFloat width = _descriptionTextView.bounds.size.width;
NSString *string = [self htmlAfterReplacingTagsAndAddingStyle];
CGRect rect = [string boundingRectWithSize:CGSizeMake(width, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:#{ NSFontAttributeName:font } context:nil];
CGRect frame = _descriptionTextView.frame;
frame.size = CGSizeMake(width, rect.size.height);
_descriptionTextView.frame = frame;
// due to #ReinierMelian...
_descriptionTextView.extContainerInset = UIEdgeInsetsMake(0, 0, 0, 0);
To remove all padding:
[textView setTextContainerInset:UIEdgeInsetsZero];
textView.textContainer.lineFragmentPadding = 0; // to remove left padding
If you want to remove Multiple new lines into single one,
In textViewDidEndEditing:
NSError *error = nil;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"\n+" options:NSRegularExpressionCaseInsensitive error:&error];
NSString *trimmedString = [regex stringByReplacingMatchesInString:string options:0 range:NSMakeRange(0, [string length]) withTemplate:#" "];
textView.text = trimmedString;

'sizeWithFont:constrainedToSize:lineBreakMode:' is deprecated: first deprecated in iOS 7.0 - Use -boundingRectWithSize:options:attributes:context:

Can anyone please help me to fix this warning?
'sizeWithFont:constrainedToSize:lineBreakMode:' is deprecated: first deprecated in iOS 7.0 - Use -boundingRectWithSize:options:attributes:context:
-(CGFloat)setLableSizeAccordingToText:(NSString*)text andSetX:(CGFloat)x Y:(CGFloat)y{
self.text = text;
CGSize maximumLabelSize = CGSizeMake(296, FLT_MAX);
CGSize expectedLabelSize = [text sizeWithFont:self.font constrainedToSize:maximumLabelSize lineBreakMode:self.lineBreakMode];
CGRect frame = CGRectMake(x, y, expectedLabelSize.width+lblHorizontalPadding , lblHeight);
self.frame = frame;
return expectedLabelSize.width + lblHorizontalPadding;
}
It is working for me
UILabel *myLabel;
CGSize textSize;
if (!SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"7.0")){
textSize = [myLabel.text sizeWithFont:[myLabel font]];
}else{
textSize = [myLabel.text sizeWithAttributes:[NSDictionary dictionaryWithObject:[myLabel font] forKey:NSFontAttributeName]];
}
Try using this
+ (CGSize)DescriptionHeight:(NSString *)str{
CGSize detailSize = [str boundingRectWithSize:CGSizeMake(300, MAXFLOAT)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:#{
NSFontAttributeName:[UIFont fontWithName:#"Cronos Pro" size:14.0f]
}
context:nil].size;
return detailSize;
}
Or u can use in this way too
CGSize stringsize = [Your_Str_Value sizeWithAttributes:#{NSFontAttributeName: [UIFont systemFontOfSize:16.0f]}];
YourBtn.frame = CGRectMake(10, 5, stringsize.width, 44);
The new sizeWithAttributes combined with NSParagraphStyle should do the job for you.
NSMutableDictionary *attributes = [NSMutableDictionary new];
[attributes setObject:self.font forKey:NSFontAttributeName];
NSMutableParagraphStyle *paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
paragraphStyle.lineBreakMode = self.lineBreakMode;
//paragraphStyle.alignment = self.textAlignment; //uncomment this if you need specific text alignment
[attributes setObject:paragraphStyle forKey:NSParagraphStyleAttributeName];
CGSize expectedLabelSize = [text sizeWithAttributes:attributes];

ios - how to have Multiple lines of NSAttributedString

There are 3 UIlabel in my TableViewCell.xib.One of them need to set attributedText with NSMutableAttributedString,the code like this:
NSString * htmlString = [NSString stringWithFormat:#"将订单状态从 %# 改变为 %# ,原因:%#",lb.order_status,lb.changed_status,lb.remark];
NSMutableAttributedString * attrStr = [[NSMutableAttributedString alloc] initWithData:[htmlString dataUsingEncoding:NSUnicodeStringEncoding] options:#{ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType } documentAttributes:nil error:nil];
NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
style.lineBreakMode = NSLineBreakByTruncatingTail;
style.lineHeightMultiple = 0;
[attrStr addAttribute:NSParagraphStyleAttributeName
value:style
range:NSMakeRange(0, attrStr.length)];
[attrStr addAttribute:NSFontAttributeName value:[UIFont fontWithName:#"Palatino-Roman" size:13.0] range:NSMakeRange(0, attrStr.length)];
lbRemark.attributedText=attrStr;
Question 1:
lbRemark cannot display with multiple-lines, but if I do not use NSAttributedString to set lbRemark then it can display with multiple-lines.Is there something wrong with NSAttributedString?
Question 2: I need my Cell to calculate it's height with lbRemark' height.
Since iOS8, you don't need to calculate the height of the label. Auto-layout will do that for you.
Attach top and bottom constraints between the UILabel and the cell - do not set a height constraint for the UILabel.
In the viewDidLoad: method of your UIViewController, just do the following (replace the 50.0f with the default height of your rows):
self.tableView.estimatedRowHeight = 50.0f;
self.tableView.rowHeight = UITableViewAutomaticDimension;
1: Set this for multiple lines:
lbRemark.numberOfLines = 0;
2: This is how to calculate height of label according to text:
NSString * htmlString = [NSString stringWithFormat:#"将订单状态从 %# 改变为 %# ,原因:%#",#"test",#"test1",#"test2"];
NSMutableAttributedString * attrStr = [[NSMutableAttributedString alloc] initWithData:[htmlString dataUsingEncoding:NSUnicodeStringEncoding] options:#{ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType } documentAttributes:nil error:nil];
NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
style.lineBreakMode = NSLineBreakByTruncatingTail;
style.lineHeightMultiple = 0;
[attrStr addAttribute:NSParagraphStyleAttributeName
value:style
range:NSMakeRange(0, attrStr.length)];
[attrStr addAttribute:NSFontAttributeName value:[UIFont fontWithName:#"Palatino-Roman" size:13.0] range:NSMakeRange(0, attrStr.length)];
lbRemark.numberOfLines = 0;
CGRect paragraphRect = [attrStr boundingRectWithSize:CGSizeMake(625, CGFLOAT_MAX)
options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
context:nil]; //here 625 is width of label, use whatever your width
NSLog(#"height = %f", paragraphRect.size.height); //it should be height for label
lbRemark.attributedText=attrStr;
Hum...finally I got a solution for it.It's not anything wrong with NSAttributedString.I implement a function(my workmate who often helped me offer it ):
static UITableViewCell *sizingLogCell = nil;
static dispatch_once_t onceToken;
if ([indentifier isEqualToString:#"logCell"]) {
dispatch_once(&onceToken, ^{
sizingLogCell = [tableView dequeueReusableCellWithIdentifier:indentifier];
});
sizingLogCell.bounds = CGRectMake(0.0f, 0.0f, CGRectGetWidth(tableView.bounds), CGRectGetHeight(tableView.bounds));
[sizingLogCell setNeedsLayout];
[sizingLogCell layoutSubviews];
[self configureLogCell:sizingLogCell forIndexPath:indexPath];
CGSize size = [sizingLogCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
return size.height + 1;
}
The function's name is :
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath indentifierForCell:(NSString *)indentifier
The most important thing is 'size.height + 1',if without '+1' label still can not display with multi-lines.

Can I figure out the numberOfLines of NSString without creating UILabel?

I just want to know number of lines, given the font, constraints, and the text. Can I figure it out without creating a UILabel?
+ (int)numberOfLines:(NSDictionary *)data{
NSString *myString = [some string calculation];
CGSize sizeConstrain = CGSizeMake(some constrain calculation);
CGSize stringSize = [myString sizeWithFont:someFont constrainedToSize:sizeConstrain];
CGRect labelFrame = CGRectMake(0,
0,
stringSize.width,
stringSize.height + 2);
UILabel *label = [[UILabel alloc]initWithFrame:labelFrame];
label.text = myString;
return label.numberOfLines;
}
Yes
+ (int)numberOfLines:(NSDictionary *)data{
NSString *myString = [some string calculation];
CGSize sizeConstrain = CGSizeMake(some constrain calculation);
CGSize stringSize = [myString sizeWithFont:someFont constrainedToSize:sizeConstrain];
return (stringSize.height/someFont.lineHeight);
}
EDIT: I used this for UITextView and iOS7
- (CGFloat) getRowsForText:(NSString*) text{
CGFloat fixedWidth = 300;
UIFont *font = [UIFont fontWithName:#"HelveticaNeue" size:14];
NSMutableParagraphStyle *paragrapStyle = [[NSMutableParagraphStyle alloc] init];
paragrapStyle.alignment = NSTextAlignmentLeft;
textStepAttr = [NSDictionary dictionaryWithObjectsAndKeys:
font,NSFontAttributeName,
paragrapStyle, NSParagraphStyleAttributeName,
nil];
NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:text attributes:textStepAttr];
CGRect rect = [attributedText boundingRectWithSize:CGSizeMake(fixedWidth, MAXFLOAT)
options:NSStringDrawingUsesLineFragmentOrigin
context:nil];
return (rect.size.height / font.lineHeight) ;
}

Equal spacing between lines of NSAttributedString with multiple font sizes for a UILabel in iOS 6

I have a multiple lines UILabel with attributed text.
All the lines in the text are of the same font, but each line is of a different font size.
I'm trying to achieve the exact same vertical space between each line.
However what is being displayed has variable spaces. It is as if something is adding a vertical margin to the font based on the font size.
CGFloat y = 0;
NSMutableAttributedString *attString=[[NSMutableAttributedString alloc] initWithString:#""];
NSArray *linesArray = [NSArray arrayWithObjects:#"One I\n",
#"Two I\n",
#"Three I\n",
#"Four I\n",
#"Five I\n", nil];
CGFloat fontSize = 10.0;
for(NSString *line in linesArray) {
NSMutableAttributedString *attributedLine = [[NSMutableAttributedString alloc] initWithString:line];
NSInteger stringLength=[line length];
[attributedLine addAttribute:NSFontAttributeName
value:[UIFont fontWithName:#"TimesNewRomanPSMT" size:fontSize]
range:NSMakeRange(0, stringLength)];
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineSpacing = 0.0f;
paragraphStyle.alignment = NSTextAlignmentRight;
[attributedLine addAttributes:#{ NSParagraphStyleAttributeName : paragraphStyle} range:NSMakeRange(0, stringLength)];
[attString appendAttributedString:attributedLine];
fontSize += 10.0;
}
UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero];
label.backgroundColor = [UIColor clearColor];
label.textColor = [UIColor blackColor];
label.numberOfLines = 0;
label.attributedText = attString;
[label sizeToFit];
CGRect newFrame = label.frame;
newFrame.size.width = self.view.frame.size.width - 40;
newFrame.origin.y = y;
newFrame.origin.x = 0;
label.frame = newFrame;
[self.view addSubview:label];
Any suggestions on the code I should use in order for it to display no space at all between each line of text?
I have been doing something similar, so maybe you could try something like this (typed in browser, watch out!):
NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
[style setAlignment: NSTextAlignmentRight];
[style setLineSpacing:0];
for(NSString *line in linesArray) {
NSMutableParagraphStyle *subStyle = [style mutableCopy];
[subStyle setMaximumLineHeight:10]; // play around with this value <-----
NSDictionary *attributes =
#{
NSFontAttributeName : [UIFont fontWithName:#"TimesNewRomanPSMT" size:fontSize],
NSParagraphStyleAttributeName : paragraphStyle,
};
[attString appendAttributedString:[[NSAttributedString alloc] initWithString:line attributes: attributes]];
fontSize += 10.0;
}

Resources