热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

xcodeios布局_国际化适配:使用Xcode构建有助于本地化的布局

作者:martindontpanic,iOS开发者,目前就职于TikTokSessions:https:developer.apple.c

作者:martindontpanic,iOS 开发者,目前就职于TikTok

Sessions: https://developer.apple.com/videos/play/wwdc2020/10219/

如果想让自己的应用服务国际市场,本地化就是一个需要认真对待的问题。本地化不仅仅是将UI文案翻译成多国语言,还需要在布局上针对不同的语言进行适配。这个 session 介绍了一些布局的准则和利用 Xcode 帮助布局适配的技巧。

几个布局准则

不管是使用手动计算布局、Auto Layout 还是 Swift UI,一些布局准则是通用的。

1 包含文本的控件,不要使用固定尺寸

按钮上一句很短的英文,翻译成另一种语言可能会很长,需要更多的宽度。另外,有些语言字符的上下会有一些修饰符号,让整个字符比英语字符更“高”,比如缅甸语。因此控件高度最好也不要固定。

下面是一段缅甸语文本和相同字号的英语:

ဤလင့်ခ်ကို ပံ့ပိုးမပေးပါ This link isn't supported

使用 Auto Layout 来计算文本控件的尺寸,不要设置固定长度约束。如果使用 Swift UI,避免显式设置 frame 为绝对值。

2 包含文本的控件之间,不要设置固定的间距

既然包含文本的控件尺寸是可变的,如果控件尺寸更大,间距就应该相应地更小,保证整个布局合适。

对于横向空间放置多个文本控件的场景,常见的布局方式是两边的控件到屏幕边缘设置固定的间距,中间的控件确定要“跟随”哪边来布局,最后留出一个可变间距,使用 greaterOrEqualTo 设置一个间距最小值。如图:

5ddcf16b6005e81f2dc554ef491c7f8d.png

3 尽量允许文本多行显示

手机屏幕的横向空间本身很有限,如果文本本身较长,就需要允许文本折行布局。

众所周知,UILabel 默认是单行文本布局,设置 numberOfLines = 0 即可支持多行布局。

4 在有限的空间内不要放置太多的文本控件

例如在横向空间内放置多个文字按钮,文字稍长就容易因为空间不足而被截断。

Xcode 布局调试工具

Xcode 为开发者提供了一组调试工具,可以让开发者方便地调试布局在多种语言下的表现。

Document Preview

Document Preview 可以在多种屏幕尺寸、屏幕方向和语言条件下预览 Storyboard 布局的效果。

我们随便用 Storyboard 搭个界面:

c3a6ea3b11bb8a8aa55378e37cbe5fa5.png

在菜单中依次点击 Editor -> Preview ,即可打开 Document Preview。

92171b54169dafccee52f60b3a3bf0c2.png

点击右下角按钮可以切换预览语言:

3a0c1619cb837224bc239dd93d06789f.png

分割线上方是项目支持的所有语言,不用多说。下面的几个 Pseudolanguage 是用来方便调试布局效果的“伪语言”。

第一个 Double-length Pseudolanguage 会让文本重复两次,方便预览在长文本下的布局适配效果。

我们尝试切一下,所有文本都买一送一了。

7d8f46483c31c3c1a52cccb0d17a7086.png

可以看到大标题被截断了,我们把这个 UILabelnumberOfLines 属性设置为0,让它自动折行。

5f7cf6f215bcabb698c4b3f7434d322c.png

其他的几种 Pseudolanguage 也很有趣,Emotional Pseudolanguage 会把所有的文本变成 Emoji:

fde6adc6d83cc4c980f3e2b410b82233.png

Accented Pseudolanguage 会在字符上下加一些符号,这个在 Unicode 中叫做 Combining Diacritical Marks(组合附加符号)。有些语言(比如上面提到的缅甸语)会有这种符号,如上文所说,文本控件的高度也需要针对不同语言动态适配。

80dacf12b327c001fdbf06d0dd5a1806.png

Scheme Options

对于使用代码自定义的布局效果,Document Preview 就有些力不从心了,我们需要把 App 实际跑起来验证。

我们看一下官方视频中提供的一个例子:

d11a6228f25a046631c37057374d6edd.png

界面上四个按钮横向排开,用一个 UIStackView 包裹。横向空间很紧张,如果按钮文字再长一些势必被截断。用 Double-length Pseudolanguage 预览一下看:

288f7f7e1732d95f085cd3bc1e799d83.png

这里苹果的工程师创建了一个 UIStackView 子类,当判断出横向空间不足以容纳所有子视图时,自动调整为纵向布局。

class ReadjustingStackView: UIStackView {
    
    ...
    
    override func layoutSubviews() {
        adjustOrientation()
    }
    
    @objc
    func adjustOrientation() {
        // Always attempt to fit everything horizontally first
        axis = .horizontal
        alignment = .firstBaseline
        
        let desiredStackViewWidth = systemLayoutSizeFitting(UIView.layoutFittingCompressedSize).width
        if let parent = superview {
            let availableWidth = parent.bounds.inset(by: parent.safeAreaInsets).width - (leadingConstraint.constant * 2.0)
            if desiredStackViewWidth > availableWidth {
                axis = .vertical
                alignment = .fill
            }
        }
    }
}

将 Storyboard 上的 UIStackView 改成这个 ReadjustingStackView,然后打开Edit Scheme -> Options,将 App Language 设置为 Double-length Pseudolanguage,再启动调试:

b923387b9bb49e674cd99ad6900b4d93.png

和预期中一样,按钮变成了纵向布局。

fd2d132be93201e434aecea82f22137e.png

这里也体现了上文提到的布局原则4,在有限的空间内不要放置太多控件。如果 UI 需要横向排列多个按钮,可以考虑用图标代替文字,这样就不会有多语言适配问题了。

运行时 App 语言还可以设置为 Right-to-Left Pseudolanguage,可以模拟从右到左书写的语言,比如阿拉伯语、希伯来语。苹果官方的设计规范要求,当界面语言为从右到左语言时,整个界面布局需要左右镜像反转,原先左对齐的文本排版也要改为右对齐。这个伪语言选项在调试从右到左语言适配效果时非常有用。我们用这个选项把第一个 Demo 跑起来试一试:

354324ab59a825ba0d523c488c395725.png

可以看到 UITextField 中输入的文本已经是右对齐了。但是两个 UILabel 的文本还是左对齐。我们将它们的 text alignment 设为 natural,这样当界面语言是 RTL 语言时就会自动右对齐。重新跑起来,是我们期望的效果了:

99c9b2c70d86b169ae9d8b057de1641c.png

预览动态字体效果

动态字体是苹果在 iOS 7 就引入的特性,可以让 App 的字体大小跟随用户在 iOS 设置中选择的大小。这个特性对视力减退的用户还是很友好的,你看那些老人机的界面字号都特大。老实说作为常年对着电脑屏幕的程序员,尝试把手机字号调大以后也觉得贼舒服。

如果你的应用支持了动态字体,界面自然也需要根据字号动态布局。Xcode 也提供了几种预览动态字体效果的功能。

一个是 Environment Override,在启动应用调试之后可以在 Debug 窗口上面的工具栏点开。这个功能除了调试动态字体之外还可以调试 Dark Mode 和其他的 Accessibility 选项。

7c22f85e19d3a07328410f45612a05f6.png

另一个是 Accessibility Inspector,在菜单栏选择 Xcode -> Open Developer Tool -> Accessibility Inspector 即可打开。

a76afebe107d8b11c06e2207958d36ce.png

打开以后选中想要控制的 Target,选中设置 Tab 就可以设置字体了。

a05cb0ea21436405e668991372518fe0.png

想进一步了解动态字体,可以看2017年的WWDC Session Building Apps with Dynamic Type[1]

额外放送:怎样适配从右到左语言

很多出海应用都不会放过阿拉伯语市场,毕竟沙特是真的土豪。如前文提到的,适配阿拉伯语这种从右到左的语言,需要将整个界面左右镜像翻转,左对齐的文本需要变为右对齐。

下面介绍一些适配从右到左语言的方法,主要编译自苹果官方文档 Internationalization and Localization Guide[2] 的 Supporting Right-to-Left Languages 章节。

创建从右到左的界面

只要使用了 Auto Layout,且确保横向约束使用 leading/trailing 而不是 left/right 创建,界面布局就会自动镜像翻转。如果应用针对 iOS 9 以上系统链接,UIKit 控件也会自动翻转。

以下的界面元素不需要翻转:

  • 视频控制按钮和时间轴

  • 无指向性的图片

  • 时钟

  • 音符与乐谱

  • 图表

获取布局方向

在 iOS 中使用 UIView 的一个类方法 userInterfaceLayoutDirectionForSemanticContentAttribute:获取布局方向。例如:

if ([UIView userInterfaceLayoutDirectionForSemanticContentAttribute:view.semanticContentAttribute] == UIUserInterfaceLayoutDirectionRightToLeft) {
    ...
}

设置文本对齐

在 iOS 9以上环境下,默认的文本对齐方式是 NSNaturalTextAlignment,在英语、中文这类从左到右语言环境下是左对齐,在从右到左语言下是右对齐。

如果一个文本控件希望在从左到右语言下是右对齐,从右到左语言下是左对齐,就需要获取一下布局方向然后手动设置了。

if ([UIView userInterfaceLayoutDirectionForSemanticContentAttribute:view.semanticContentAttribute] == UIUserInterfaceLayoutDirectionRightToLeft) {
    label.textAlignment = NSTextAlignmentLeft;
} else {
    label.textAlignment = NSTextAlignmentRight;
}

处理双向文本

如果一段文本中阿拉伯语和英语字符混在一起,阿拉伯语字符应当从右到左排列,英语字符则是从左到右,这种就是双向文本。

iOS 的文本控件已经帮我们处理好了双向文本的排版。文本整体的书写方向是通过运行时检查文本前几个字符来确定的。

但这种自动确定方向的机制有时会不符合预期。比如一段文本大部分是阿拉伯语,但开头几个单词是英语,这给时整个文本的方向就会判定为从左到右。这种情况下想要强制指定文本的书写方向,可以使用下文介绍的 Unicode 标记字符。

对于遵循 UITextInput 协议的文本输入控件,可以使用 setBaseWritingDirection:forRange: 方法来指定文本书写方向。

Unicode 标记字符

Unicode 提供了一组不可见的字符用于标记文本的书写方向。

  • U+202A left-to-right embedding character,表示接下来的字符从左到右书写。
  • U+202B right-to-left embedding character,表示接下来的字符从右到左书写。
  • U+202C pop directional formatting character,表示字符方向标记作用范围结束,和上面两个字符配合使用。

举个例子,电话号码在任何语言都应该是从左到右书写的。可以在电话号码的首尾两边加上 U+202A 和 U+202C 来保证在任何语言文本中都正确显示。

// Wrap the plus (+) prefix and phone number in left-to-right directional markers
NSString *phoneNumber = @"408-555-1212";
NSString *localizedPhoneNumber = [NSString stringWithFormat:@"\u202A%@\u202C", phoneNumber];

  • U+200E left-to-right mark character,用来标识整段文本从左到右书写。
  • U+200F right-to-left mark character,标识整段文本从右到左书写。

如果一段文本的起始是一个变量,比如是一个用户名,此时首位字符是不确定的。要将文本的书写方向固定,就可以使用这两个字符。

手动指定视图和控件方向

在 iOS 9 之后,可以使用 UIView 的属性 semanticContentAttribute 来指定在从右到左语言环境下应该怎样展示。

例如视频进度条不应当在从右到左语言下翻转,可以设置为 UISemanticContentAttributePlayback。更多选项可以查看官方文档:UISemanticContentAttribute[3]

翻转图片

在从左到左语言下翻转图片,有以下几种方法:

  • 调用UIImageimageFlippedForRightToLeftLayoutDirection方法将图片翻转。
  • 为从右到左语言提供单独的本地化图片资源,详情参见 Adding Additional Resources You Want to Localize[4]
  • 在 Xcode 工程中添加从右到左的图片资源,然后在代码中手动设置。

人工测试的重要性

在视频末尾,session 主讲人特地强调了人工测试的重要性。尽管苹果为我们提供了多种工具,但有些本地化问题还是要靠 native speaker 的人工测试来发现。例如术语翻译的前后不一致、文本截断和缩略、脱离上下文的不适当翻译。尤其在提供新的语言支持、或做了大的功能变动的时候,人工测试是很有必要的。

小结

无论开发者使用哪种语言,国际用户的数量都是占多数的。用户看到应用针对自己的语言做了适配会很开心,本地化做得好的应用会留给用户正面的第一印象,有助于在当地市场构建良好的用户关系和声誉。在进行 UI 设计时,需要考虑多种语言对界面外观的影响,遵循本地化设计的几个布局原则。如果在设计和编码阶段就充分考虑了本地化,最后只需要很少的调整就能让应用完美支持多种语言。最后,由说当地语言的人员进行测试,是保证应用良好的本地化质量的重要步骤。

感谢阅读~

推荐阅读

Universal Links 新变化:让触达更广更快

关注我们

我们是「老司机技术周报」,每周会发布一份关于 iOS 的周报,也会定期分享一些和 iOS 相关的技术。欢迎关注。

4633c4154ead36000b6a3d7a4de019d4.png

关注有礼,关注【老司机技术周报】,回复「2020」,领取学习大礼包。

支持作者

这篇文章的内容来自于 《WWDC20 内参》。在这里给大家推荐一下这个专栏,专栏目前已经创作了 108 篇文章,只需要 29.9 元。点击【阅读原文】,就可以购买继续阅读 ~

WWDC 内参 系列是由老司机周报、知识小集合以及 SwiftGG 几个技术组织发起的。已经做了几年了,口碑一直不错。 主要是针对每年的 WWDC 的内容,做一次精选,并号召一群一线互联网的 iOS 开发者,结合自己的实际开发经验、苹果文档和视频内容做二次创作。

参考资料

[1]

Building Apps with Dynamic Type: https://developer.apple.com/videos/play/wwdc2017/245/

[2]

Internationalization and Localization Guide: https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPInternational/Introduction/Introduction.html#//apple_ref/doc/uid/10000171i-CH1-SW1

[3]

UISemanticContentAttribute: https://developer.apple.com/documentation/uikit/uisemanticcontentattribute

[4]

Adding Additional Resources You Want to Localize: https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPInternational/LocalizingYourApp/LocalizingYourApp.html#//apple_ref/doc/uid/10000171i-CH5-SW17




推荐阅读
author-avatar
阿川那小子
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有