Counting whitespace and blanks in UILabel text - iphone

I have a strike-out subview in my cell's labels and its width is set accordingly to the text in the row. The number of lines in the cell's label is set to 2, and when there are two lines I have two strike-outs set on the label.
This is what I'm doing for labels with just one line of text:
UIView *crossout = [[UIView alloc] init];
crossout.frame = CGRectMake(x, y, w + 5, 2);
crossout.backgroundColor = [UIColor colorWithRed: 0.0 / 255 green:175.0 / 255 blue: 30.0 / 255 alpha:1.0];
crossout.tag = 1;
[self.contentView addSubview:crossout];
I'm getting the width (w) by:
CGFloat w = [self.label.text sizeWithFont:[UIFont systemFontOfSize:15.0f]].width;
When I have a second strike-out, I simply subtract w from the length of my label to get the width of the second strike-out.
Problem though is that w doesn't account for white spaces or blanks in the label's text, so it won't always look consistent across the line breaks.
How do I calculate w so that it includes the white spaces and blanks?

as i know you can use this for UITextField but you can give it a try..
NSString *resultingString = self.label.text;
NSCharacterSet *whitespaceSet = [NSCharacterSet whitespaceCharacterSet];
if ([resultingString rangeOfCharacterFromSet:whitespaceSet].location == NSNotFound) {
//here you can put your code
}

To get the number of in-line whitespaces in your string you could try the following code:
NSCharacterSet* whitespaceSet = [NSCharacterSet whitespaceCharacterSet];
NSArray* substringsArray = [yourStringToCheck componentsSeparatedByCharactersInSet: whitespaceSet]
NSLog(#"Number of whitespaces : %d", [substringsArray count]);
Or, maybe even better (allthough this probably doesn't account for tabs etc.):
NSLog(#"Number of whitespaces : %d", [[yourStringToCheck componentsSeparatedByString:#" "] count]);
Another option (NSMutableString):
NSUInteger replacementCount = [yourStringToCheck replaceOccurrencesOfString:#" " withString:#" " options:NSLiteralSearch range:NSMakeRange(0, [receiver yourStringToCheck])];

Related

Crop last sentence from html string if it does not fit webView (iphone)

I have an array of texts that have bold parts in them. There is no rule where this bold word or sentence is, so i am using webView to display html string with bold tags where necessary. Now my webViews do not scroll anywhere and sometimes the text does not fit in them.
So here is my question:
I want to crop text so, that it would fit my webView and the cropping wouldn't be in the middle of sentence, but instead would crop out whole sentence if it doesn't fit. So in the end, the text should end with final sentence that fits.
What I did was strip html tags from the html sentence, calculate the height that the text takes up then remove last part of text, separated with "." (dot) if it exceeds required height.
Here is the code to do this.
NSString *returnedString = [[[NSString alloc] initWithString:htmlText] autorelease];
CGSize a = [[returnedString stripHtml] sizeWithFont:font constrainedToSize:CGSizeMake(sizeToFit.width, 999)];
NSMutableArray *sentences = [[NSMutableArray alloc] initWithArray:[returnedString componentsSeparatedByString:#"."]];
while (a.height > sizeToFit.height) {
_lastTextExceededLimits = NO;
if (sentences.count > 1) {
// -2 because last sentence is not deletable and contains html tags
NSString *sentence2 = [sentences objectAtIndex:(sentences.count - 2)];
NSString *stringToReplace = [NSString stringWithFormat:#"%#%#",sentence2, #"."];
returnedString = [returnedString stringByReplacingOccurrencesOfString:stringToReplace withString:#""];
[sentences removeLastObject];
} else
returnedString = [returnedString stringByReplacingOccurrencesOfString:[sentences lastObject] withString:#""];
a = [[returnedString stripHtml] sizeWithFont:font constrainedToSize:CGSizeMake(sizeToFit.width, CGFLOAT_MAX)];
}
[sentences release];
return returnedString;

How to add UILabel between two strings

i have this code to show some texts in a UITextview..i just want to add a UILabel between these strings.i am getting text in this formate, 1 this is first text 2 this is second text 3 this is third text,,i want to add or append UILabel between numeric character and text.my code for showing text is
NSMutableString *combined = [NSMutableString string];
for(NSUInteger idx = 0; idx < [delegatee.allSelectedVerseEnglish count]; idx++) {
[combined appendFormat:#" %d %#",
idx + 1,
[delegatee.allSelectedVerseEnglish objectAtIndex:idx]];
}
NSNumberFormatter * f = [[NSNumberFormatter alloc] init];
NSNumber * n = [f numberFromString:combined];
NSLog(#"N: %#", n);
maintextview.text =combined;
combined is the text in the above formate ,and maintextview is the UITextview.
am also getting the string range between two sentence
- (void)textViewDidEndEditing:(UITextView *)textView
{
if (textView == maintextview) {
mainpopupview.frame =CGRectMake(0, 0, 768, 1004) ;
[self.view addSubview:mainpopupview];
NSRange selectedRange = [textView selectedRange];
NSString *backString = [maintextview.text substringToIndex:selectedRange.location];
NSRange backRange = [backString rangeOfString:#" " options:NSBackwardsSearch];
NSRange backRangee = [backString rangeOfString:#" " options:NSBackwardsSearch];
int myRangeLenght = backRangee.location - backRange.location;
NSRange myStringRange = NSMakeRange (backRange.location, myRangeLenght);
NSString *forwardString = [maintextview.text substringFromIndex:backRange.location];
NSLog(#"%#",[[forwardString componentsSeparatedByString:#" "] objectAtIndex:1]);
NSLog (#"%#", [maintextview.text substringWithRange:myStringRange]);
NSString * myStringTxt = [[forwardString componentsSeparatedByString:#" "] objectAtIndex:1];
NSLog(#"1 %#", myStringTxt);
// maintextview.textColor = [UIColor yellowColor];
NSRange myStringRangee = [maintextview.text rangeOfString:myStringTxt];
[maintextview select:self];
maintextview.selectedRange = myStringRangee;
is there any way to do this.
Thanks in advance.
I don't know what user interaction you need here, but if you're just displaying the text for the user, but could you replace your UITextView with a UIWebView (loading static text via loadHTMLString:baseURL:, using html markup to set the color of the text)? I refer to the UITextView documentation:
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.
If you really need to do this with separate UI controls (much more complicated than just using a UIWebView) you don't "insert" the UILabel in the text, but rather you'd probably have one control for the text up to the point of the color change, another control for the text of a different color or what have you, another control for the rest of the text. It would get hairly pretty quickly (unless it was laid out like a grid, and even then it's a hassle compared to a UIWebView).

Change the Font Style - (Set Lable text in All-Caps format ) in Objective C

I want to set the UILable text font style in Small-Caps format like below image.
Please give me the solution for this if anyone know,
Thanks.
:)
If I didn't get you wrong, is this what you want?
NSString *uppercaseString = [yourString uppercaseString];
Fonts available in iOS don't have "capitalic style". You should add own font or try to create font using function CTFontDescriptorCreateCopyWithFeature.
I think that the simplest way will be to build attributed string (NSAttributedString) with mixed font sizes.
For iOS 7 custom fonts, the method is described by Anthony Mattox. For system font I do not know a way.
Typesetting a font in small caps on iOS
you can try with this
NSString* str=#"mudit";
label.text=[str uppercaseString];
it will give you the output like this:MUDIT
To make the UILabel render as an upper-case string, where the first letter of each word is larger, you can do something like this:
#implementation CapitalicTextLabel
- (void)drawRect:(CGRect)rect
{
// Drawing code
NSArray* words = [self.text componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetCharacterSpacing(context, 1);
CGContextSetFillColorWithColor(context, [self.textColor CGColor]);
CGAffineTransform myTextTransform = CGAffineTransformScale(CGAffineTransformIdentity, 1.f, -1.f );
CGContextSetTextMatrix (context, myTextTransform);
CGFloat x = 0;
float centeredY = (self.font.pointSize + (self.frame.size.height - self.font.pointSize) / 2) - 2;
CGFloat firstLetterSize = self.font.pointSize * 1.4;
for (NSString* word in words)
{
NSString* letter = [[word substringToIndex:1] uppercaseString];
CGContextSelectFont(context, [self.font.fontName cStringUsingEncoding:NSASCIIStringEncoding], firstLetterSize, kCGEncodingMacRoman);
CGContextShowTextAtPoint(context, x, centeredY, [letter cStringUsingEncoding:NSASCIIStringEncoding], [letter length]);
x = CGContextGetTextPosition(context).x;
NSString* restOfWord = [[[word substringFromIndex:1] uppercaseString] stringByAppendingString:#" "];
CGContextSelectFont(context, [self.font.fontName cStringUsingEncoding:NSASCIIStringEncoding], self.font.pointSize,
kCGEncodingMacRoman);
CGContextShowTextAtPoint(context, x, centeredY, [restOfWord cStringUsingEncoding:NSASCIIStringEncoding], [restOfWord length]);
CGPoint v = CGContextGetTextPosition(context);
x = CGContextGetTextPosition(context).x;
}
}
#end
This implementation doesn't handle splitting across multiple-lines or honor the TextAlignment setting, This would be should be simple enough to add afterwards.
Example:
try with this one
NSString *string = #"askdfjgjksdfgh";
NSString *upString = [string uppercaseString];
NSLog(#"U %#", upString);
It is not possible to change the font size or type of a individual letter within a UILabel.
What you want to do is to have 2 labels, one in the begging for the first bigger letter and one right after that for the remaining word.
In order to access the first letter and the rest of the word you may use:
NSString * word = #"COMPLETED";
NSString * firstLetter = [word substringToIndex:1];
NSString * remainingWord = [word substringFromIndex:1];
What you see in the picture are probably pictures of words and not UILabels.

How to know the length of NSString that fits a UILabel with fixed size?

I know NSString has methods that determine the frame size for it, using NSString UIKit Additions, sizeWithFont......
How about the other way around? I mean if I have a fixed frame size, how do I know how many characters or words for a NSString that can fit into it?
If I know this, I can cut off the NSString easily.
thanks
It might not be the most elegant solution, but you could do something like this:
- (NSString *)string:(NSString *)sourceString reducedToWidth:(CGFloat)width withFont:(UIFont *)font {
if ([sourceString sizeWithFont:font].width <= width)
return sourceString;
NSMutableString *string = [NSMutableString string];
for (NSInteger i = 0; i < [sourceString length]; i++) {
[string appendString:[sourceString substringWithRange:NSMakeRange(i, 1)]];
if ([string sizeWithFont:font].width > width) {
if ([string length] == 1)
return nil;
[string deleteCharactersInRange:NSMakeRange(i, 1)];
break;
}
}
return string;
}
Then call it like this:
NSString *test = #"Hello, World!";
CGFloat width = 40.0;
UIFont *font = [UIFont systemFontOfSize:[UIFont labelFontSize]];
NSString *reducedString = [self string:test reducedToWidth:width withFont:font];
NSLog(#"%#", reducedString);
You cannot know/determine the number of characters that fits in a UILabel with fixed width because some characters are smaler than others, eg l and m.
There are two options:
Use Mono-Space-Fonts (each character has also a fixed width). Then determine the width for one char in your font with your font-size and calculate the number of chars
Allow any number of characters and check on insert if the inserted characters fit.
You have to know what behaviour you want to have. What should happen if there is text that does not fit. If you only want to truncate (like the solution of mortenfast does) then just use UILineBreakModeTailTruncation for the lineBreakMode-property of your UILabel (there are more options, like TruncateHead, Clip, Word Wrap)
Or you just just use the lineBreak property and set it to NSLineBreakByCharWrapping and move on with your life. https://stackoverflow.com/a/29088337/951349
Thanks #Morten. I've updated the sample code to handle word separation. It also eliminates extra spaces in between words. It has not been tested in the field, but my tests have, thus far, proven OK. Please update at your leisure if you find improvements or bug/glitch fixes.
-(NSString*)string:(NSString*)sourceString reducedToWidth:(CGFloat)width withFont:(UIFont*)font {
// if full string is within bounds, simply return the full string
if( [sourceString sizeWithFont:font].width <= width ) return sourceString;
// break up string into words. if <= 1 word, return original string
NSArray* words = [sourceString componentsSeparatedByString:#" "];
NSInteger numWords = [words count];
if( numWords <= 1 ) return sourceString;
// our return var. we populate as we go
NSMutableString* str = [NSMutableString string];
// temp var to test with before adding to return string
NSMutableString* strTemp = [NSMutableString string];
// string to hold word LESS spaces
NSString* strWordTemp = nil;
// the word we're currently on
NSInteger numWord = 0;
// whether we need to add a space (when not last word)
Boolean addSpace = NO;
// loop through our words....
for( NSString* strWord in words ) {
// which word we're on
numWord++;
// eliminate white space
strWordTemp = [strWord stringByReplacingOccurrencesOfString:#" " withString:#""];
// if this word is empty or was a space(s), skip it
if( [strWordTemp isEqualToString:#""] ) continue;
// append to temp string
[strTemp appendString:strWordTemp];
// if we're still within the bounds...
if( [strTemp sizeWithFont:font].width <= width ) {
// default = no extra space
addSpace = NO;
// if we're not the last word, add a space & check for length
if( numWord < numWords ) {
[strTemp appendString:#" "];
// if adding space made it too long, then just don't add it!
if( [strTemp sizeWithFont:font].width > width ) {
// it was too long with space, so we'll just add word
[str appendString:strWordTemp];
break;
}
// otherwise, it's OK to add the space
else addSpace = YES;
}
// append to return string and continue
[str appendFormat:#"%#%#", strWordTemp, ( addSpace ? #" " : #"" )];
}
// otherwise, we're done
else break;
}
// return our result
return str;
}

UITextView position

Is there a way to find ypos in a UITextView, or/and find which row that currently marker is active?
you need to do some calculation
find cursor position by
NSRange cursorPosition = [tf selectedRange];
substring from cursor position use this sub string to calculate width of the string by
sizeWithFont:constrainedToSize:
and then divide it by width of the your TextView width.. it will give you at which line your cursor is... It's logically seems correct... haven't tried it... try it let me know if it is working or not..
Something like that:
- (int) getCurrentLine: (UITextView *) textView{
int pos = textView.selectedRange.location;
NSString *str =textView.text;
NSCharacterSet *charset = [NSCharacterSet whitespaceAndNewlineCharacterSet];
int num = pos;
for (; num< str.length; num++){
unichar c = [str characterAtIndex:num];
if ([charset characterIsMember:c]) break;
}
str = [str substringToIndex:num];
CGSize tallerSize = CGSizeMake(textView.frame.size.width - 16, 999999);
CGSize lc1 = [#"Yyg" sizeWithFont: textView.font constrainedToSize:tallerSize lineBreakMode:UILineBreakModeWordWrap];
CGSize lc = [str sizeWithFont: textView.font constrainedToSize:tallerSize lineBreakMode:UILineBreakModeWordWrap];
lc.height = lc.height / lc1.height;
return lc.height;
}