背景:阿拉伯语使用者占世界人口的6%,使用阿拉伯字母,为从右至左书写的文字,主要通行于18个阿拉伯国家及4个国际组织的官方语言。以阿拉伯语作为母语的人数超过2.6亿人。阿拉伯语在全球范围使用者总计目前已经突破4.4亿人。
语言特点:是由28个辅音字母和12个发音符号(不包括叠音符)组成的拼音文字。书写顺序从右往左横行书写,翻阅顺序也是由右往左。
[UIView appearance].semanticContentAttribute = UISemanticContentAttributeForceRightToLeft;
[UISearchBar appearance].semanticContentAttribute = UISemanticContentAttributeForceRightToLeft;
[[UINavigationBar appearance] setSemanticContentAttribute:UISemanticContentAttributeForceRightToLeft];
self.view.semanticContentAttribute = UISemanticContentAttributeForceRightToLeft;
Semantic 设置为spatial
前提: 使用 left right 或者 frame的情况下都是指定了具体的方向和坐标位置,系统不会进行调整,使用Leading和Trailing系统会自动调整。
[UIApplication sharedApplication].userInterfaceLayoutDirection
[UIView userInterfaceLayoutDirectionForSemanticContentAttribute:view.semanticContentAttribute]
view.effectiveUserInterfaceLayoutDirection
解决方案:修改CollectionViewFlowLayout
flipsHorizontallyInOppositeLayoutDirection是指开启 一个布尔值,指示水平坐标系是否在适当的时间自动翻转。 这个属性是默认关闭的 如果发生无法反转的话,我们需要这样打开。
flipsHorizontallyInOppositeLayoutDirection是readonly的,我们需要自定义layout,并重写getter方法。
header和cell不会改变textAlignment
然而系统却不会自动帮我们将left和right调换。我们需要手动去适配它。
方法一:在需要的地方判断以下。
方法二:hook
方法一:
[[(NSMutableParagraphStyle *)paraStyle setAlignment:NSNaturalTextAlignment];
方法二:hook
拉丁语和数字是始终LTR的,开发者需要自己适配。
情景一:固定文字,如Label。(demo)
我们的解决方式跟苹果推荐的一致,多语言拼接其他LTR字符。
情景二:文字输入,如TextField
WWDC 2013 Making Your App World-Ready: International Text > Bidirectional Text
setBaseWritingDirection:forRange:
UITextWritingDirectionNatural
苹果不建议修改。
navigation需要单独设置,解决方案是hook了UINavigationController的initWithNibName:bundle:,单独设置UINavigationController的view的semanticContentAttribute
hook了UISwipeGestureRecognizer的setDirection:
系统不会为我们自动做处理,大部分图片也不需要处理,只需要手动旋转一下类似箭头的图片即可。
方法一:系统提供了- (UIImage *)imageFlippedForRightToLeftLayoutDirection NS_AVAILABLE_IOS(9_0);
只有系统语言切换有用,应用内切换不生效,所以自己单独写方法
方法二:修改xcassets中对应图片资源的direction
方法三:使用Localize Resources
方法四:
- (NSImage *)flipImage:(NSImage *)image
{
NSImage *existingImage = image;
NSSize existingSize = [existingImage size];
NSSize newSize = NSMakeSize(existingSize.width, existingSize.height);
NSImage *flippedImage = [[[NSImage alloc] initWithSize:newSize] autorelease];
[flippedImage lockFocus];
[[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh];
NSAffineTransform *transform = [NSAffineTransform transform];
[transform translateXBy:existingSize.width yBy:0];
[transform scaleXBy:-1 yBy:1];
[transform concat];
[existingImage drawAtPoint:NSZeroPoint fromRect:NSMakeRect(0, 0, newSize.width, newSize.height) operation:NSCompositeSourceOver fraction:1.0];
[flippedImage unlockFocus];
return flippedImage;
}
Types of controls and content that should not flip in a right-to-left language are:
Video controls and timeline indicators
Images, unless they communicate a sense of direction, such as arrows
Clocks
Music notes and sheet music(乐谱)
Graphs (x– and y–axes always appear in the same orientation)
if ([NSApp userInterfaceLayoutDirection] == NSUserInterfaceLayoutDirectionRightToLeft) {
NSArray *toolbarItems = [[self.toolbar items] copy];
for (NSToolbarItem *item in toolbarItems) {
[self.toolbar removeItemAtIndex:toolbarItems.count-1];
[self.toolbar insertItemWithItemIdentifier:item.itemIdentifier atIndex:0];
}
}
WKWebview虽然继承于UIView,但是它的setSemanticContentAttribute:会有问题,会导致Crash(看一下广告,会不会crash)。
Nearby中,如果对cell顺序有要求,需要自定义layout,非常麻烦。
小卡片travel按钮图标有问题。
filter进度条应从右边开始。
PA页滚动方向反了。
FreeTrial页描述文字对齐方式不对。
ChatsCell中,没有使用约束,所以RTL没有生效。
ChatsList广告没有适配。
Chat页有问题。
InstagramMediaBrowserViewController有问题。
Profile页整个都有问题。
需要全面测试,很多细节可能出现问题。
建议设计师增加流程,提供设计图时,如果有图片需要适配RTL,需提前说明,不然都按LTR来做。
测试时,尽量使用应用内切换语言。
1.尽量都使用约束来做UI,且不要用left和right,改用leading和trailing。
2.文字对齐如果是左右对齐的话,都使用NSNaturalTextAlignment。
3.多语言遇到拼接字符串的话,要谨慎。其他LTR语言中,如果是拼接字符串,第一个字符是RTL语言,会出现显示问题,应该使用localizedStringWithFormat(使用后,底层会去判断去除该字符之后的字符串的第一个字符)。
4.如果遇到需要适配排列方向的collectionView,提前自定义layout。
5.需要镜像的图片使用恰当的方法实现。
RLT官方文档
WWDC2015
WWDC2016