J'arrive enfin à la lutte avec la mise en page automatique et n'arrive pas à comprendre comment obtenir un soutien de droite à gauche (RTL) pour fonctionner de la manière que j'attendais/souhaitais ...
J'ai conçu la vue dans Interface Builder comme indiqué:
L'application résultante fonctionnant normalement lorsque vous utilisez l'anglais:
Cependant, lors du passage à une langue RTL (l'arabe en l'occurrence), la vue entière bascule (ce qui est excellent), mais le texte de la variable UILabel
est toujours aligné à gauche. Je m'attendrais à ce qu'il soit parfaitement aligné pour le maintenir contre la UIImageView
.
Clairement, il me manque quelque chose et/ou cela n'est pas couvert par la mise en page automatique.
Suis-je censé définir la textAlignment
manuellement lors de l'utilisation d'un langage RTL?
Vous voulez NSTextAlignmentNatural
. Cela implique l'alignement du texte à partir de la langue de l'application chargée ( pas à partir du script).
Pour iOS 9 et versions ultérieures (à l'aide de Xcode 7), vous pouvez définir cela dans le scénario (choisissez l'option --- alignement). Si vous devez cibler des versions antérieures, vous devez créer un point de vente pour l'étiquette et définir l'alignement dans awakeFromNib
.
- (void)awakeFromNib {
[[self label] setTextAlignment:NSTextAlignmentNatural];
}
Pour moi, ces solutions ne m'ont pas aidé et j'ai fini par faire quelque chose d'assez laid, mais c'est la seule qui a fait l'affaire. Je l'ai ajouté dans la catégorie 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
Pour détecter la langue que j'ai utilisée cette SO réponse .
Suivi de la réponse de Ken
Définir textAlignment
sur NSTextAlignmentNatural
n'est pas possible sur UILabel
, une exception sera levée:
Terminating app due to uncaught exception 'NSInvalidArgumentException',
reason: 'textAlignment does not accept NSTextAlignmentNatural'
Cela fonctionne lors de l’utilisation de texte attribué et ceci peut être défini dans Interface Builder comme indiqué:
Cependant, il semblerait que le texte attribué ne soit pas pris en compte lors de la localisation du storyboard.
Pour résoudre ce problème, j'ai laissé la UILabel
configurée en clair dans Interface Builder et créé une NSAttributedString
avec le texte de l'étiquette, définissez l'alignement sur la chaîne attribuée et l'affectez à la propriété 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;
}
Cela fonctionne bien dans ce cas simple, mais je peux le voir tomber lorsque vous avez besoin d'un style de chaîne attribué plus complexe. Mais évidemment, dans ce cas, vous utiliseriez probablement simplement NSLocalizedString
ou des équivalents lors de la création de NSAttributedString
.
@Aviel répond en tant que extension 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
}
}
}
Comment l'utiliser ?
label.text = "كتابة باللغة العربية" // Assign text
label.decideTextDirection() // Decide direction
Je pense que vous ne voulez pas utiliser l'alignement du texte dans ce cas, pour une étiquette.
Vous pouvez simplement laisser la largeur être déterminée par intrinsicContentSize et supprimer toutes les contraintes de largeur sur l'étiquette. Vous obtiendrez l'effet souhaité du texte de l'étiquette aligné sur la vue.
Pour l'axe x, vous n'avez besoin que de cette contrainte entre label et imageview: [Imageview] - [label]
Ce n'est qu'une contrainte d'espacement horizontal. Pas de tête ni de fuite vers Superview.
vous pouvez utiliser MyLayout pour faciliter l’aide RTL et LRT.
@Aviel répond comme une extension Swift 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
Cette fonction m'a aidé
-(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;
}