AutoLayout + RTL + UILabel文本对齐

时间:2013-09-11 14:48:40

标签: ios interface-builder autolayout

我终于开始与Auto Layout进行斗争了,似乎无法弄清楚如何从右到左(RTL)支持以我期望/想要的方式工作......

我在Interface Builder中设计了视图,如下所示:

IB

使用英语时,生成的应用程序按预期运行:

English

然而,当切换到RTL语言(在这种情况下为阿拉伯语)时,整个视图翻转(这很棒),但UILabel的文本仍然保持对齐。我希望它能够与UIImageView保持一致。

Arabic

显然我遗漏了一些东西和/或自动布局没有涵盖这一点。

我是否应该在使用RTL语言时手动设置textAlignment

9 个答案:

答案 0 :(得分:25)

你想要NSTextAlignmentNatural。这可以从加载的应用程序语言中推断出文本对齐方式(不是来自脚本)。

对于iOS 9及更高版本(使用Xcode 7),您可以在故事板中设置它(选择---对齐选项)。如果您需要定位早期版本,则需要为标签创建一个插座,并在awakeFromNib中设置对齐方式。

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

答案 1 :(得分:11)

对我来说,这些解决方案没有帮助,我最终做了一件非常丑陋的事情,但它是唯一一个为我做这个伎俩的人。我将其添加为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

要检测我使用的语言this SO answer

答案 2 :(得分:4)

对于标签,我认为您不希望在这种情况下使用文本对齐方式。

您可以通过intrinsicContentSize确定宽度,并删除标签上的任何宽度约束。您将获得与视图对齐的标签文本所需的效果。

对于x轴,您只需要在label和imageview之间使用此约束: [imageview的] - [标号]

这只是一个水平间距约束。没有领先或跟踪超级视图。

答案 3 :(得分:4)

跟随Ken的回答

textAlignment无法将NSTextAlignmentNatural设置为UILabel,这会导致异常被抛出:

Terminating app due to uncaught exception 'NSInvalidArgumentException',
reason: 'textAlignment does not accept NSTextAlignmentNatural'
使用属性文本时

可以正常工作,并且可以在Interface Builder中设置可以,如下所示:

attributed text natural alignment

但是,在本地化故事板时,似乎没有拾取属性文本。

为了解决这个问题,我在Interface Builder中将UILabel配置为plain,并使用标签的文本创建NSAttributedString,在属性字符串上设置对齐并将其分配给标签{{ 1}} property:

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或等价物。

答案 4 :(得分:4)

答案 5 :(得分:1)

您可以使用MyLayout轻松支持RTL和LRT。

答案 6 :(得分:0)

这个功能帮助了我

-(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 :(得分:0)

@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
        }
    }
}

用法

label.text = "كتابة باللغة العربية" // Assign text
label.decideTextDirection()          // Decide direction

答案 8 :(得分:0)

这是我的版本。它更简单,并且可以处理源文档中的多种语言。

要点是要使用dominantLanguage:

let lang = tagger.dominantLanguage

代码段:

 extension UILabel {
    func determineTextDirection () {
        guard self.text != nil else {return}

        let tagger = NSLinguisticTagger(tagSchemes: [.language], options: 0)
        tagger.string = self.text

        let lang = tagger.dominantLanguage

        let rtl = lang == "he" || lang == "ar"

        self.textAlignment = rtl ? .right : .left
    }
}

用法:

titleLabel.text = "UILabel היפוך שפה עבור"
titleLabel.determineTextDirection()

最后:请注意,如果该应用程序已本地化并且您可能依赖于电话语言-解决方案是: “ RTL的自然文本对齐”: 即:

titleLabel.textAlignment = .natural

enter image description here

当您的应用显示使用不同语言的多行时,请使用NSLinguisticTagger。或允许您以任何语言免费搜索(不论本地语言)。