私はようやく自動レイアウトと格闘し始めており、右から左へ(RTL)をサポートする方法を期待どおりに機能させる方法を理解できないようです...
以下のようにInterface Builderでビューを設計しました。
英語を使用すると、結果として得られるアプリが期待どおりに実行されます。
ただし、RTL言語(この場合はアラビア語)に切り替えると、ビュー全体が反転します(これは素晴らしい)が、UILabel
のテキストは左揃えのままです。 UIImageView
に対応するために、正しく調整されると思います。
明らかに何かが足りない、および/またはこれは自動レイアウトの対象外です。
RTL言語を使用する場合、textAlignment
を手動で設定する必要がありますか?
NSTextAlignmentNatural
が必要です。これは、読み込まれたアプリケーション言語からテキストの配置を推測します(スクリプトからnot)。
IOS 9以降(Xcode 7を使用)では、ストーリーボードでこれを設定できます(---配置オプションを選択)。以前のリリースをターゲットにする必要がある場合は、ラベルへのアウトレットを作成し、awakeFromNib
に配置を設定する必要があります。
- (void)awakeFromNib {
[[self label] setTextAlignment:NSTextAlignmentNatural];
}
私にとってこれらの解決策は役に立たず、結局醜いことをすることになりましたが、それが私にとってトリックを作った唯一のものです。 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 。
ケンの答えからフォローアップ
textAlignment
をNSTextAlignmentNatural
に設定することは、UILabel
では不可能であり、例外がスローされます。
Terminating app due to uncaught exception 'NSInvalidArgumentException',
reason: 'textAlignment does not accept NSTextAlignmentNatural'
属性付きテキストを使用する場合、これは機能します。これは、次のようにInterface Builderで設定できます。
ただし、ストーリーボードをローカライズすると、属性付きテキストが取得されないように見えます。
これを回避するには、UILabel
をInterface Builderでプレーンとして構成したままにし、ラベルのテキストでNSAttributedString
を作成し、属性付き文字列に配置を設定して、ラベルの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
または同等のものを使用するだけでしょう。
@Avielの回答Swift 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
この場合、ラベルにテキストの配置を使用したくないと思います。
あなただけの幅がintrinsicContentSizeによって決定されるようにして、ラベルの幅の制約を取り除くことができます。ビューに位置合わせされたラベルテキストの望ましい効果が得られます。
X軸の場合、ラベルとイメージビューの間にのみこの制約が必要です:[imageview]-[label]
これは、水平方向の間隔の制約にすぎません。スーパービューの先頭または末尾はありません。
MyLinearLayout を使用すると、RTLおよびLRTを簡単にサポートできます。
Swift 4 UILabel拡張としての@Avielの回答
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
これが私のバージョンです。よりシンプルで、ソースドキュメント内の複数の言語も処理します。
主なポイントは、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
アプリが異なる言語で複数の行を表示する場合は、NSLinguisticTaggerを使用します。または、ローカルに関係なく、任意の言語での無料検索を許可する場合。
この機能は私を助けました
-(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;
}