UILabel Vertical align missing space - ios

I've used UILabel for showing text with vertical alignment. I'm showing text as character by character with vertical alignment. Actually It's an moving text by alignment with CABasicAnimation. But my problem here is
Each line should show one character, but when I try stretch label width to
show single character, Some character is wiped partially. see screen
shot of xib(sample with small text).. Or try to extend frame size, some row show single character and some shows double character.
Space is missing between words. see screenshot.
How can I fix it with my xib? Answer also acceptable with programmatically.
Note: Text used in this example "Some text with long".

You don't need vertical align. Just make the UILabel wider and input a \n after every character of the string.
NSString *longString = #"This is a very very long string";
NSString *labelString = #"";
self.label.text = labelString;
self.label.numberOfLines = 500; //just put a big number or calculate something
for (int n=longString.length - 1; n > -1; --n) {
labelString = [NSString stringWithFormat:#"%#\n%#", [longString substringWithRange:NSMakeRange(n, 1)], labelString];
self.label.text = labelString;
}

Related

Xcode UILabel bug? Line spacing cropping text with a UILabel

I have some designs I'm following for an iOS project. The font used is Avenir with relatively tight line spacing.
Some of these labels will have dynamic text, so I can't just make the label's size larger since the size should be determined by the content.
By default line spacing for a UILabel ends up pretty large.
If I adjust the Line Height Multiple or the Max Height, the text along the top ends up cropped.
It should behave like this (Affinity Designer)...
Is there a way to handle this?
Thanks for your help!
This works for me. By adding
minimumLineHeight
let string = NSMutableAttributedString(string: venue.name)
let style = NSMutableParagraphStyle()
style.lineHeightMultiple = 0.68
style.minimumLineHeight = nameLabel.font.lineHeight
string.addAttribute(NSAttributedString.Key.paragraphStyle,
value: style,
range: NSMakeRange(0, venue.name.count))
nameLabel.attributedText = string
Unfortunately the UILabel has several quirks when it comes to vertical adjustments. A somewhat hacky solution is to move the baseline of the first line down as needed. Depending on if your string ends with a newline, and the amount of tightening you do, you might need to add one or two extra newlines also, otherwise the rendering engine will clip the last line.
The code snippet assumes that self.label already has an attributed string assigned to it, and that it has line separator character 0x2028 between the lines. This is usually true when entering multi-line text in IB.
// 0x2028 is the unicode line separator character
// Use \n instead if it is what you have
// or calculate the length of the first line in some other way
NSInteger lengthOfFirstLine = [self.label.text componentsSeparatedByString:#"\u2028"][0].length;
NSMutableAttributedString *s = [[NSMutableAttributedString alloc] initWithAttributedString:self.label.attributedText];
// Add two more blank lines so that the rendering engine doesn't clip the last line
[s appendAttributedString:[[NSAttributedString alloc] initWithString:#"\n\n"]];
// Move the baseline offset for the first line down
// the other lines will adjust to this
// 50 is a value you will have to find what looks best for you
[s addAttribute:NSBaselineOffsetAttributeName value:#(-50) range:NSMakeRange(0, lengthOfFirstLine)];
self.label.attributedText = s;

How to keep a space at the end of the string in ios, objective C without changing its UI(position)

I have created a label programmatically.it's with is equal to the device width and I have aligned it to right.so it shows the text from right.
like this
titleLabel.textAlignment = NSTextAlignmentRight;
then I gave a text to the label.
titleLabel.text = #"Flight Summary";
but I want to keep a space after y letter in summary, without decreasing the width of the label.I tried with using string format like this.
titleLabel.text =[NSString stringWithFormat:#"%# ", #"Flight Summary "];
but nothing happned.how can I do that.hope your help for this.thanx.
To reduce the complexity of subclassing, you can take UIView and UIlabel, set frame of UIView to screen width and take UILabel frame as screenwidth - 8 (or whatever pixels is appropriate for you). Manage the frames and add both to mainview, this way you will be able to achieve the look.
Try this
titleLabel.text = #"abcd exadgdf \u{200c}""
You can also do one more thing. You can use attributed string and set attributed text to titlelabel without formatting string like this
NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:#"ABCD "];
titleLabel.attributedText = attrString;

Center a UIButton's title vertically for words longer than its width

I want to implement a UIButton so the title appears centered inside, no matter the length of the text.
The problem I'm facing is that the button's width and the font size need to be of a fixed value because they need to be consistent with the rest of the UI details. And I can't truncate the text either.
I am fine with splitting words, but only when the word that does not fit the title's width.
Currently it's working fine for 1-line and 2-line texts (with spaces) but when the title contains one long word without spaces, it centers the first line only (please see the images attached).
I guess I would like to do something like:
if (button.currentTitle.length > (buttonWidth/characterWidth)) { //2-line title buttons
// Do something special to fix the problem
}
But I've tried setting all these and non of them worked:
[button.titleLabel setTextAlignment:NSTextAlignmentCenter];
[button.titleLabel setBaselineAdjustment:UIBaselineAdjustmentAlignCenters];
[button setTitleEdgeInsets:UIEdgeInsetsMake(0, 0, 20, 0)];
button.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
Any ideas/suggestions to keep the titleLabel vertically centered?
You can wrap the title by characters, setting your button's line break mode to NSLineBreakByCharWrapping (by default it wraps at word boundaries), only when it contains words that do not fit.
if (button.currentTitle.length > (buttonWidth/characterWidth)) { //2-line title buttons
// Check if title contains long words
NSArray *words = [button.currentTitle componentsSeparatedByString:#" "];
for (NSString *word in words) {
if (word.length > (buttonWidth/characterWidth)) {
// Set the line break mode to char wrapping
button.titleLabel.lineBreakMode = NSLineBreakByCharWrapping;
break; // No need to continue :-)
}
}
}

How do i make Circled numbers in UITextView

Please Help..im not sure were to begin
..How do i show numbers with circles around them in my UITextView
like 1 2 3 4 .............but each number inside a circle eg http://openclipart.org/people/gsagri04/GS_Numbers.svg
i was hopping to get numbers from an array and show them on screen ....but each number living inside a circle like lotto numbers
# the moment i only have a An array [1,2,3,4],...A button .....and UItextView to show the final output
xcode 4.
If I understood your need correctly, you want to display following special characters in your textview:
① ② ③ ④ ⑤ ⑥ ⑦ ⑧ ⑨ ⑩ ⑪ ⑫ ⑬ ⑭ ⑮ ⑯ ⑰ ⑱ ⑲ ⑳
The easiest approach is to copy+paste these characters, and replace the numeric characters in the content string you need to display in the textview. You may write a NSString category method to handle this job, in sake of code reuse.
#Chris Chen's solution is pretty nifty, as you can change the characters on the go. But if you do not want to use the characters, you may use the following code to add circles to your textView.
UITextPosition *pos = textView.endOfDocument;// textView ~ UITextView
for (int i=0;i<words*2-1;i++){// *2 since UITextGranularityWord considers a whitespace to be a word, words = number of words in the textView.
UITextPosition *pos2 = [textView.tokenizer positionFromPosition:pos toBoundary:UITextGranularityWord inDirection:UITextLayoutDirectionLeft];
UITextRange *range = [textView textRangeFromPosition:pos toPosition:pos2];
CGRect resultFrame = [textView firstRectForRange:(UITextRange *)range ];
if (check whether word at this text position is a number){
UIView* circleView = [[UIView alloc] initWithFrame:resultFrame];
circleView.backgroundColor = [UIColor clearColor];
circleView.layer.borderColor = <color of your choice, probably same as text color>;
circleView.layer.borderWidth = <the width you want to set the border thickness to>;
circleView.layer.cornerRadius = <a float value that makes the rectangle look like a circle>;
circleView .tag = 125;
[textView circleView ];
}
pos = pos2;
}
The code should be placed in the UITextView delegate method textViewDidChange. And make sure you remove the circle view before all this code, hence the tag(125).

iOS: sizeWithFont for single character is different than in a string?

I am trying to determine the precise position of a character in a UILabel, say:
(UILabel *)label.text = #"Hello!";
I'd like to determine the position of the 'o'. I thought that I could just sum the widths of all the preceding characters (or the whole preceding string) using sizeWithFont. The width value I get though is bigger by about 10% than what it should be. Summing the widths of individual letters (i.e. [#"H" sizeWithFont...] + [#"e" sizeWithFont...] + l... + l...) accumulates more error than [#"Hell" sizeWithFont...].
Is there a way of accurately determining the position of a single glyph in a string?
Many thanks.
Yes, but not in a UILabel and not using sizeWithFont:.
I recently worked with Apple Developer Support, and apparently sizeWithFont: is actually an approximation. It becomes less accurate when your text (1) wraps across multiple lines and (2) contains non-latin characters (i.e. Chinese, Arabic), both of which cause line spacing changes not captured by sizeWithFont:. So, don't rely on this method if you want 100% accuracy.
Here are two things you can do:
(1) Instead of UILabel, use a non-editable UITextView. This will support the UITextInput protocol method firstRectForRange:, which you can use to get the rect of the character you need. You could use a method like this one:
- (CGRect)rectOfCharacterAtIndex:(NSUInteger)characterIndex inTextView:(UITextView *)textView
{
// set the beginning position to the index of the character
UITextPosition *beginningPosition = [textView positionFromPosition:textView.beginningOfDocument offset:characterIndex];
// set the end position to the index of the character plus 1
UITextPosition *endPosition = [textView positionFromPosition:beginningPosition offset:1];
// get the text range between these two positions
UITextRange *characterTextRange = [textView textRangeFromPosition:beginningPosition toPosition:endPosition]];
// get the rect of the character
CGRect rectOfCharacter = [textView firstRectForRange:characterTextRange];
// return the rect, converted from the text input view (unless you want it to be relative the text input view)
return [textView convertRect:rectOfCharacter fromView:textView.textInputView];
}
To use it, (assuming you have a UITextView called myTextView already on the screen), you would do this:
myTextView.text = #"Hello!";
CGRect rectOfOCharacter = [self rectOfCharacterAtIndex:4 inTextView:myTextView];
// do whatever you need with rectOfOCharacter
Only use this method for determining the rect for ONE character. The reason for this is that in the event of a line break, firstRectForRange: only returns the rect on the first line, before the break.
Also, consider adding the method above as a UITextView category if you're gong to be using it a lot. Don't forget to add error handling!
You can learn more about how firstRectForRange: works "under the hood" by reading the Text, Web, and Editing Programming Guide for iOS.
(2) Create your own UILabel by subclassing UIView and using Core Text to render the strings. Since you're doing the rendering, you'll be able to get the positions of characters. This approach is a lot of work, and only worthwhile if you really need it (I, of course, don't know the other needs of your app). If you aren't sure how this would work, I suggest using the first approach.
Well fonts are smart now a day and take in respect the position of a character to its pervious character.
Here is an example on how the starting position of the letter o:
NSRange posRange = [hello rangeOfString:#"o"];
NSString *substring = [hello substringToIndex:posRange.location];
CGSize size = [substring sizeWithFont:[UIFont systemFontOfSize:14.0f]];
No you can do the same for the string including the letter o and substract the size found in the string without the letter o.
THis should give the an nice start position of the letter and the size.
in ios6 you can do using attributed string
NSMutableAttributedString *titleText2 = [[NSMutableAttributedString alloc] initWithString:strHello];
NSRange posRange = [hello rangeOfString:#"o"];
[titleText2 addAttributes:[NSDictionary dictionaryWithObject:[UIFont systemFontOfSize:14.0f] forKey:NSFontAttributeName] range:NameRange];
and set your textView with this attributed string

Resources