AutoLayout + RTL + выравнивание текста UILabel
Я, наконец, собираюсь бороться с Auto Layout и не могу понять, как получить поддержку справа налево (RTL), чтобы работать так, как я ожидал/хочу...
Я разработал представление в Interface Builder, как показано ниже:
![IB]()
В результате приложение работает как ожидается при использовании английского языка:
![English]()
Однако при переключении на RTL-язык (в данном случае арабский) весь просмотр переворачивается (что отлично), но текст UILabel
по-прежнему выравнивается по левому краю. Я ожидаю, что он будет выровнен по правому краю, чтобы поддерживать его против UIImageView
.
![Arabic]()
Очевидно, что я что-то упускаю и/или это не покрывается Автоманией.
Я должен установить textAlignment
вручную при использовании языка RTL?
Ответы
Ответ 1
Вы хотите NSTextAlignmentNatural
. Это указывает выравнивание текста с загруженного языка приложения ( не из script).
Для iOS 9 и более поздних версий (с использованием Xcode 7) вы можете установить это в раскадровке (выберите параметр --- выравнивания). Если вам нужно настроить таргетинг на более ранние версии, вам необходимо создать выход на метку и установить выравнивание в awakeFromNib
.
- (void)awakeFromNib {
[[self label] setTextAlignment:NSTextAlignmentNatural];
}
Ответ 2
Для меня эти решения не помогли, и я закончил тем, что делал что-то довольно уродливое, но это единственное, что помогло мне. Я добавил его как категорию NSString
:
NSString + Extras.h:
#import <Foundation/Foundation.h>
@interface NSString (Extras)
- (NSTextAlignment)naturalTextAligment;
@end
NSString + Extras.m:
#import "NSString+Extras.h"
@implementation NSString (Extras)
- (NSTextAlignment)naturalTextAligment {
NSArray *tagschemes = [NSArray arrayWithObjects:NSLinguisticTagSchemeLanguage, nil];
NSLinguisticTagger *tagger = [[NSLinguisticTagger alloc] initWithTagSchemes:tagschemes options:0];
[tagger setString:self];
NSString *language = [tagger tagAtIndex:0 scheme:NSLinguisticTagSchemeLanguage tokenRange:NULL sentenceRange:NULL];
if ([language rangeOfString:@"he"].location != NSNotFound || [language rangeOfString:@"ar"].location != NSNotFound) {
return NSTextAlignmentRight;
} else {
return NSTextAlignmentLeft;
}
}
@end
Чтобы определить язык, на котором я использовал этот ответ SO.
Ответ 3
@Aviel ответ как быстрое расширение UILabel
//MARK: UILabel extension
extension UILabel {
func decideTextDirection () {
let tagScheme = [NSLinguisticTagSchemeLanguage]
let tagger = NSLinguisticTagger(tagSchemes: tagScheme, options: 0)
tagger.string = self.text
let lang = tagger.tagAtIndex(0, scheme: NSLinguisticTagSchemeLanguage,
tokenRange: nil, sentenceRange: nil)
if lang?.rangeOfString("he") != nil || lang?.rangeOfString("ar") != nil {
self.textAlignment = NSTextAlignment.Right
} else {
self.textAlignment = NSTextAlignment.Left
}
}
}
Как его использовать?
label.text = "كتابة باللغة العربية" // Assign text
label.decideTextDirection() // Decide direction
Ответ 4
Я думаю, вы не хотите использовать выравнивание текста в этом случае для ярлыка.
Вы можете просто определить ширину, определяемую intrinsicContentSize, и удалить любые ограничения ширины на метке. Вы достигнете желаемого эффекта текста меток, выровненного по отношению к представлению.
Для оси x вам нужно только это ограничение между меткой и изображением:
[ImageView] - [метка]
Это ограничение только по горизонтали. Нет ведущего или завершающего просмотра.
Ответ 5
Следуйте за ответом Кена
Настройка textAlignment
на NSTextAlignmentNatural
невозможна на UILabel
, это приведет к тому, что получится исключение:
Terminating app due to uncaught exception 'NSInvalidArgumentException',
reason: 'textAlignment does not accept NSTextAlignmentNatural'
Он работает при использовании атрибутного текста, и этот может быть установлен в Interface Builder, как показано ниже:
![attributed text natural alignment]()
Однако, по-видимому, при локализации раскадровки приписанный текст не подбирается.
Чтобы обойти это, я оставил UILabel
, настроенный как простой в Interface Builder, и создал текст NSAttributedString
с текстом ярлыка, установил выравнивание в атрибутной строке и присвоил ей свойство label attributedText
:
-(void)viewDidLoad
{
[super viewDidLoad];
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.alignment = NSTextAlignmentNatural;
NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:self.lbl.text];
[string addAttribute:NSParagraphStyleAttributeName
value:paragraphStyle
range:NSMakeRange(0, string.length)];
self.lbl.attributedText = string;
}
Это прекрасно работает в этом простом случае, но я вижу, что он падает, когда вам нужно более сложное приписываемое стилирование строк. Но, очевидно, в этом случае вы, вероятно, просто используете NSLocalizedString
или эквиваленты при создании NSAttributedString
.
Ответ 6
Эта функция помогла мне
-(void)fnForWritingDirection:(UILabel*)label textFor:(NSString *)stringForText{
NSMutableAttributedString* attrStr = [[NSMutableAttributedString alloc] initWithString: [stringForText stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
[paragraphStyle setBaseWritingDirection:NSWritingDirectionRightToLeft];
[attrStr addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, [attrStr length])];
label.attributedText=attrStr;
}
Ответ 7
Вы можете использовать MyLinearLayout для простой поддержки RTL и LRT.
Ответ 8
@Aviel ответ как быстрое расширение 4 UILabel
extension UILabel {
func decideTextDirection () {
let tagScheme = [NSLinguisticTagScheme.language]
let tagger = NSLinguisticTagger(tagSchemes: tagScheme, options: 0)
tagger.string = self.text
let lang = tagger.tag(at: 0, scheme: NSLinguisticTagScheme.language,
tokenRange: nil, sentenceRange: nil)
if lang?.rawValue.range(of: "he") != nil || lang?.rawValue.range(of: "ar") != nil {
self.textAlignment = NSTextAlignment.right
} else {
self.textAlignment = NSTextAlignment.left
}
}
}
usage
использования
label.text = "كتابة باللغة العربية" // Assign text
label.decideTextDirection() // Decide direction