AWERTL 1.0.0

AWERTL 1.0.0

字节跳动维护。



AWERTL 1.0.0

  • 作者
  • 字节跳动

接入指南

pod 'AWERTL'

// 设置在 RTL 下需要二次反转的 image names,如方向指示性图片
[AWERTLManager sharedInstance].flipImageNames = @[@"directional_image_name1", @"directional_image_name2"/*, ...*/];
// 在 RTL 环境下,启动 AWERTL
[AWERTLManager sharedInstance].enableRTL = YES;

什么是 RTL

RTLRight To Left(从右到左)的缩写,表示从右向左书写的语言,例如阿拉伯语和希伯来语等。使用这种语言的用户习惯从右往左阅读文本、使用功能。

以抖音为例,下图为普通界面

普通界面

下图为 RTL 界面

普通界面

可见,除了文本方向变换成从右向左以外,各 UI 控件也遵循「先右后左」的布局规则,交互逻辑也要相应地反向:例如在 push 中新页面从左侧进入,pop 时向左滑动退出等。

系统方案

iOS 从 9.0 开始提供了对 RTL 界面的系统方案支持,主要是提供了 leadingtrailingUILayoutGuide 来替代在 RTL 中需要翻转的场景下的 leftright,以及 UIViewsemantic attributes —— 也就是说在 RTL 环境中,leading 等同于 righttrailing 等同于 left,而在一般环境下反之。

系统方案有以下不足:

  1. 为了支持 RTL,必须使用 AutoLayout

    首先,现有代码中有大量 Frame 布局,改造成本过高;

    其次,在某些场景下(例如直播弹幕,单列关注),出于性能考虑,不能改用 AutoLayout

  2. 需要使用者对该使用 leading 还是 left 有清晰的要求

    由于历史原因,项目中大量现存的 AutoLayout 代码是 leadingleft 不分的,大量使用者直接将 leading 替代 left 使用,没有考虑 RTL 场景下的用例。

  3. 不支持 iOS 8 及以下系统

  4. 交互的适配可能需要大量的 If Else,例如 pop 手势左滑还是右滑等

AWERTL 的原理

AWERTL 使用 Window 镜像方案来适配 RTL:

  1. 将整个窗口以 y 轴为对称轴翻转
  2. 不可翻转的元素再次以自身的 y 轴为对称轴翻转
  3. 调整各个组件,例如使文本右对齐等

RTL

原理非常清晰,直接支持元素位置镜像和交互镜像,无论使用 AutoLayout 还是 Frame 布局都可以,编写代码的方式保持不变。

关键的问题在于如何判断不可翻转的元素

  1. 文本类元素

    文本类元素无条件需要正面对着观众,因此 UILabel、UITextView、YYLabel 等组件默认属于 不可翻转的元素

  2. 非方向指示性的图片

    除了带有左右方向指示性质的图片(例如返回箭头按钮)需要跟随屏幕一起翻转以外,大部分的图片(例如视频封面图)都需要保持正常的方向而非镜像。因此 UIImageView 除非其中的 image 带有左右方向指示性质,否则就属于 不可翻转的元素

  3. 已经用其他方式做了 RTL 适配的页面

    由于在 RTL 环境下,系统会对它提供的一些组件自动做 RTL 适配,因此不需要我们来做二次的镜像适配,它们也属于 不可翻转的元素,例如 系统键盘 Status Bar PHPhotoPickerViewController 等。此项还包括 UIWebViewController SFSafariViewController 等,因为前端应当负责进行页面的 RTL 适配。

  4. 其它业务方希望保持正向的元素

    例如视频播放器的页面、录制页的 Camera 试图等。

因此,AWERTL 也按照上述的思路来设计 API。

UIView 提供一个 awertl_viewType 的属性,默认值为 AWERTLViewTypeAuto,表示自动根据上述的规则(1,2,3)来进行 RTL 适配,自行选择合适的方案。除此之外,这个属性还可以被设置为以下几种值:

  1. AWERTLViewTypeInherit

    表示继承父元素的方案,这也是大多数 UIView 的 Auto 默认选择的方案

    inherit

  2. AWERTLViewTypeNormal

    不管父元素的方案,强制正向。比如文本、普通图片、视频播放器

    normal

  3. AWERTLViewTypeFlip

    不管父元素的方案,强制反向。比如带左右方向指示性的图片

    flip

  4. AWERTLViewTypeNormalWithAllDescendants

    不管父元素的方案,强制正向,同时强制所有的子元素全部正向。比如系统键盘

    normal_wad

  5. AWERTLViewTypeFlipWithAllDescendants

    不管父元素的方案,强制反向,同时强制所有的子元素全部反向。在工程中暂无实例

    flip_wad

一句话总结

一般情况下,RTL 会自动适配;如果 RTL 下某个 UIView 反了,通过设置 view.awertl_viewType = AWERTLViewTypeNormal 即可修正

FAQ

Q: 接入了一个已经用系统方案实现了 RTL 的第三方库,如何兼容?

A: 如果此库提供整个页面 UI,建议通过单独的 UIWindow 使用该库,并设置 window.awe_rtlviewType = AWERTLNormalWithAllDescendants;如果此库提供零散的 UI 组件,建议添加组件类的 Catagory,并在其中重写 - (AWERTLViewType)awertl_automaticViewType 方法,告知 AWERTL 不处理相关的控件