iOS RTL 工作内容如下:
1、基本系统所有的控件都要进行RTL适配(iOS的UIView,UILabel,UITextField 等已经适配)
2、所有自定义组件需要进行RTL适配
3、所有页面布局需要进行RTL适配,如果之前是frame 布局,需要改成autoLayout布局进行RTL适配
4、所有图片不能带有文字,要不无法进行RTL适配,iOS 已经适配加载本地图片(启动图除外),加载网络图片有待适配
5、Rn的Facebook 官方控件已经进行了RTL适配(Facebook 完成)
6、一些系统手势,比如侧滑,需要进行适配
7、混合文本(比如中文+阿拉伯语言)需要适配
图片处理
处理带方向的图片,这个部分有两种方式可以处理,要么让UI切两套图,分别展示,或者是把图片翻转一下,当然,图片不能带文字,这里得多说一句,经过这一次的教训,我发誓以后再也不要用带文字的图片了,如果只是带方向的图片,翻转就行了,但是图片带文字那就玩不转了,只能用几套图,还有国际化的时候,图片带文字,也不好处理,很不幸,我项目中很多带文字的图片,我只能一个一个去修改
布局约束和Frame
iOS 目前没有整套AOP的方案
1.如果是用了frame 布局的话,需要每个页面单独判断是否是阿拉伯语言进行修改
2.如果是autoLayout ,那么控件的相对布局也是需要每个页面单独去修改
3.如果是控件内部展示的内容,比如UIView,UILabel等等,可以按照网上的方法去修改
每种控件适配RTL如下:
[UIView appearance].semanticContentAttribute = UISemanticContentAttributeForceRightToLeft;
[UISearchBar appearance].semanticContentAttribute = UISemanticContentAttributeForceRightToLeft;
[[UINavigationBar appearance] setSemanticContentAttribute:UISemanticContentAttributeForceRightToLeft];
针对目前项目
1、本地图片iOS 统一了图片加载入口,添加黑白名单处理,在图片加载入口处判断之后再镜像图片
2、远程图片暂没处理(后端根据http头部语言或者特定的字段处理)
3、启动图没处理
iOS各类原生控件处理
UILabel
通过 hook initWithFrame 和 setTextAlignment 来修改文字位置,后发现应用内切换语言没法做到文字左右变换主要是因为系统的 NSTextAlignmentNatural 没有办法在应用内切换的语言的时候,改变text的排布 如果把 NSTextAlignment 设置成 NSTextAlignmentLeft,那么切换阿拉伯语言的时候就会自动变成NSTextAlignmentRight
全局修改NSMutableParagraphStyle 会影响label的布局
UITextField
很多控件在应用内切换语言和重启切换语言表现不一样。比如UITextField 的placeHolder 没有办法设置TextAlignment,如果是重启进入的话,那么系统会自动适配,但是应该内切换的话,系统没有办法适配
UIProgressView
UIProgressView 在适配TRL的时候遇到 UIImage 镜像导致圆角消失利用的是如下方法
[UIImage imageWithCGImage:self.CGImage
scale:self.scale
orientation:UIImageOrientationUpMirrored];
由于UIProgressView是利用UIImageView进行进度播放的,所以图片翻转有问题,怀疑是系统的bug
目前的解决方案是自定义UIProgressView 用UIView 来代替UIImageView 来显示进度,这样就不需要执行imageWithCGImage 这个方法
UIImageView
本来想hook UIImageView 的setImage 方法来进行RTL适配,结果发现会导致键盘的键没法显示
//RTL图片翻转
-(void)rtl_setImage:(UIImage *)image{
UIImage * imm = [image oem_imageFlippedForRightToLeftLayoutDirection];
return [self rtl_setImage:imm];
}
方案1.但是Hook 系统的基础控件的方法本身就过于危险,系统很多控其他件可能是基于这些基础控件定制的,而且还要做白名单处理,这个方案的可靠性有待验证。
方案2. 如果修改sd_setImage的方法,就要全局修改,之后每个模块都要引入business 的 flip 图片
方案3.后端根据RTL放回RTL对应的图片url
UISlide
1.滑条在RTL模式下,会导致一边圆角一边不是圆角的问题,通过
//重写layoutSubviews
-(void)layoutSubviews{
[super layoutSubviews];
if (@available(ios 14.0,*)) {
CALayer * llay = self.layer.sublayers.firstObject;
if (llay.sublayers.count > 1) {
llay.sublayers[1].cornerRadius = self.axisH/2;
}
}else{
NSArray * llays = self.layer.sublayers;
if (llays.count > 1) {
CALayer * llay = llays[1];
llay.cornerRadius = self.axisH/2;
}
}
}
2.UISlider iOS 15系统,UIView 设置了RTL也没用,需要transform
// 只有iOS15 才需要翻转
if(@available(ios 15.0,*)){
if ([[RCTI18nUtil sharedInstance] isRTLForced]) {
self.transform = CGAffineTransformMakeScale(-1.0, 1.0);
}
}
auotlayout注意点
所有利用NSLayoutAttributeLeft 和 NSLayoutAttributeRight 布局的都需要修改 NSLayoutAttributeLeft 对应 NSLayoutAttributeLeading NSLayoutAttributeRight 对应 NSLayoutAttributeTrailing
一些翻译细节问题
1.在国际化的时候,就是strings 文件没有报错能编译过去,但是如果加载不出来的话,那么string文件也是有问题的,阿拉伯语遇到这种情况,下面这句翻译多了中间多了””,导致所有的阿拉伯语翻译都不能显示
"Can not jump to the privacy settings page, please go to the settings page by self, thank you" = "إذا تعذّر الانتقال إلى صفحة "إعدادات الخصوصية"، فيرجى الانتقال إلى صفحة "الإعدادات" بنفسك، شكرًا لك";
2.时间日期,阿拉伯的时间日期,不能用阿拉伯数字显示,用通过localeWithLocaleIdentifier 方法格式化时间日期
+ (NSString *)dof_LocaleGetNSStringFromNSDate:(NSDate *)date withFormatter:(NSString *)format
{
NSDateFormatter * formatter = [NSDateFormatter new];
NSLocale *locale = nil;
if ([[[HGInternationalization sharedInstance] convertSystemLanguangeCodeToUnifyLanguangeCode:HGCurrentLanguage.code] hasPrefix:@"ar"]) {
locale = [NSLocale localeWithLocaleIdentifier:@"ar"];//注意这里不是ar-DZ
}else{
locale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"];
}
formatter.locale = locale;
[formatter setDateFormat:format];
NSString * res = [formatter stringFromDate:date];
return res;
}