Autolayout + Rtl + Uilabel Text Alignment

AutoLayout + RTL + UILabel text alignment

You want NSTextAlignmentNatural. That infers the text alignment from the loaded application language (not from the script).

For iOS 9 and later (using Xcode 7), you can set this in the storyboard (choose the --- alignment option). If you need to target earlier releases, you'll need to create an outlet to the label and set the alignment in awakeFromNib.

- (void)awakeFromNib {
[[self label] setTextAlignment:NSTextAlignmentNatural];
}

UILabel text alignment when English and Hebrew mixed as text?

Here is a sample you could be inspired with.

Note: I don't know how you create your all text, so I don't know how you'll know what's in English or what in Hebrew, but you'll get the idea.

NSMutableAttributedString *attrStr = [[NSMutableAttributedString alloc] initWithString:@"I bless You, God, for creating the fruit of the vine:\n בָּרוּךְ אַתָּה יְיָ אֱלֹהֵֽינוּ מֶֽלֶךְ הָעוֹלָם, בּוֹרֵא פְּרִי הַגָּֽפֶן."];

NSMutableParagraphStyle *englishParagraphStyle = [[NSMutableParagraphStyle alloc] init];
[englishParagraphStyle setAlignment:NSTextAlignmentLeft];

NSMutableParagraphStyle *hebrewParagraphStyle = [[NSMutableParagraphStyle alloc] init];
[hebrewParagraphStyle setAlignment:NSTextAlignmentRight];

NSRange englishRange = NSMakeRange(0, [@"I bless You, God, for creating the fruit of the vine:" length]);
NSRange hebrewRange = NSMakeRange([@"I bless You, God, for creating the fruit of the vine:" length],
[[attrStr string] length] - [@"I bless You, God, for creating the fruit of the vine:" length]);

[attrStr addAttribute:NSParagraphStyleAttributeName
value:englishParagraphStyle
range:englishRange];
[attrStr addAttribute:NSParagraphStyleAttributeName
value:hebrewParagraphStyle
range:hebrewRange];

[myLabel setAttributedText:attrStr];

You also may want to do this before setting it to your UILabel:

[attrStr addAttribute:NSFontAttributeName
value:[UIFont whateverFontWithWhateverSize]
range:NSMakeRange(0, [attrStr length])];

How to set top-left alignment for UILabel for iOS application?

Rather than re-explaining, I will link to this rather extensive & highly rated question/answer:

Vertically align text to top within a UILabel

The short answer is no, Apple didn't make this easy, but it is possible by changing the frame size.

Multiline UILabel with right-to-left text and auto adjusted font size

Sample ImageDon't set a specific height because of that is not expanding to your amount of text.

Steps 1 - Set top, leading, trailing and height constraint and change height relation to Greater Than or Equal to

Step 2 - label.numberOfLines = 0

Step 3 - label.sizeToFit()

step 4 - label.lineBreakMode = .byTruncatingTail

UILabel + AutoLayout = error in baseline alignment

Ok, with the last example the problem is more clear.
The first thing you must know: the text inside an UILabel is, by default, vertically aligned at the center of the label.

AFAIK you can't change the vertical align to have the text aligned to the base line.

Now, look at the attached image.

Comparison

In the first example, I leaved all the default values of your sample project.
You can see that the day label and the description label are perfectly aligned: Autolayout aligns the bounds of the two labels (that are simply views, with other private subviews inside).

But, the font size is different. For the day label is the default system size (17), for the description you specified 20.

Now, if the two labels are aligned, the text is vertically center in the label, and the font size is different, obviously the baseline of the two text won't be aligned.

In the second example, I used the same font size, and you can see that the alignment is correct.

So, the possible solutions are two:

  • use the same font (with the same size) in all the labels
  • if you want to use fonts of different kind / size, you must change the position / size of the labels to have the baseline correctly aligned

This last point can be done with some calculation, and you can find some example here: Link

EDIT

Ok, I post an example.
First thing: it seems that, at the link posted, there is an error. ascender + descender + 1 is equal to the lineHeight, and not to the pointSize. I asked the author to correct it.

So, you can subclass UILabel, override viewForBaselineLayout and do something similar.
You have to add a baselineView instance variable and add it as a subview of the UILabel, since AutoLayout want the view to align to be a subview of the label.

// please note: you may need some error checking
- (UIView *)viewForBaselineLayout
{
// create the view if not exists, start with rect zero
if (!self.baselineView)
{
self.baselineView = [[UIView alloc] initWithFrame:CGRectZero];
self.baselineView.backgroundColor = [UIColor clearColor];
[self addSubview:self.baselineView];
}

// this is the total height of the label
float viewHeight = self.bounds.size.height;

// calculate the space that is above the text
float spaceAboveText = (viewHeight - self.font.lineHeight) / 2;

// this is the height of the view we want to align to
float baselineViewHeight = spaceAboveText + self.font.ascender + 1;

// if you have 26.6545 (for example), the view takes 26.0 for the height. This is not good, so we have to round the number correctly (to the upper value if >.5 and to the lower if <.5)
int integerBaseline = (int)(baselineViewHeight + 0.5f);

// update the frame of the view
self.baselineView.frame = CGRectMake(0, 0, self.bounds.size.width, (float)integerBaseline);


return self.baselineView;

}

With this approach you have to take care of few things:

  • the label must have a size at the time autolayout calls viewForBaselineLayout, and its height must not change after. So you have to fit the label to it's content size before the layout process takes place.
  • you have adjust your constraints according to the above advice (now you are fixing, for example, dayLabel with monthLabel, but you can't since dayLabel must "float" now).

I attach your project with some updates and colors for debug, only with dayLabel and descriptionLabel (I removed the others) and with updated contraints.

Wrong Layout Updated

UIButton title alignment not changing to right direction in RTL

Use right alignment from storyboard as

Sample Image

or from programmatically as

buttonShowOnMap.contentHorizontalAlignment = .left//For left alignment

buttonShowOnMap.contentHorizontalAlignment = .right//For right alignment

How to change the text alignment throughout the app at once?

You can use UIAppearance to set properties of ui elements throughout your entire app. This will work for all classes that adopt the UIAppearance protocol (UILabel, UIButton, etc).

For eaxmple, the following code will change the text alignment of all labels in your app:

[[UILabel appearance] setTextAlignment:NSTextAlignmentRight];

IIRC, UINavigationBar does not support UIAppearance, meaning that you'll need to use a custom label for the title.



Related Topics



Leave a reply



Submit