概述
本章讨论了在Qt Quick 应用程序中实现从右向左语言支持的不同方法和选项。一些常见的从右向左语言包括阿拉伯语、希伯来语、波斯语和乌尔都语。大多数更改包括确保翻译成从右向左语言的文本正确地向右对齐,以及视图、列表和网格中水平排序的内容正确地从右向左流动。
在从右到左的语言文化中,人们会很自然地从右到左扫描和阅读图形元素和文本。一般的经验法则是,内容(如照片、视频和地图)不是镜像的,但内容的定位(如应用程序布局和视觉元素的流动)是镜像的。例如,按时间顺序显示的照片应从右向左流动,水平滑块的低端范围应位于滑块的右侧,文本行应排列在可用文本区域的右侧。当视觉元素的位置与内容相关时,例如在地图上显示位置标记以指示位置时,不应镜像视觉元素的位置。此外,在一些特殊情况下,例如在使用电话中的号码拨号器和音乐播放器中的媒体播放、暂停、后退和前进按钮时,从右向左的语言使用者习惯于从左向右定位,这时你可能需要考虑到这一点。
文本对齐
(这适用于Text 、TextInput 和TextEdit 类型)。
如果没有明确设置文本项的水平对齐方式,文本元素会自动按照文本的自然阅读方向对齐。默认情况下,从左到右的文本(如英文)对齐到文本区域的左侧,而从右到左的文本(如阿拉伯文)对齐到文本区域的右侧。空文本元素的对齐方式来自QInputMethod::inputDirection(),它基于当前系统的本地化。
可以通过设置文本元素的horizontalAlignment 属性,或使用LayoutMirroring 附加属性启用布局镜像,来覆盖这种默认的基于本地的对齐方式,后者会导致任何显式的左右水平对齐方式被镜像。请注意,当设置LayoutMirroring 时,horizontalAlignment 属性值保持不变;可从effectiveHorizontalAlignment 属性读取考虑了镜像的文本元素的有效对齐方式。
// automatically aligned to the left
Text {
text: "Phone"
width: 200
}
// automatically aligned to the right
Text {
text: "خامل"
width: 200
}
// aligned to the left
Text {
text: "خامل"
horizontalAlignment: Text.AlignLeft
width: 200
}
// aligned to the right
Text {
text: "خامل"
horizontalAlignment: Text.AlignLeft
LayoutMirroring.enabled: true
width: 200
}
定位器和视图的布局方向
(这适用于Row,Grid,Flow,ListView 和GridView 类型)。
用于水平定位和模型视图的类型有layoutDirection 属性,用于控制布局的水平方向。将layoutDirection 设置为Qt.RightToLeft 会使项目从右向左布局。默认情况下,Qt Quick 遵循从左到右的布局方向。
水平布局方向也可以通过LayoutMirroring 附加属性反转。这将导致定位器和视图的有效layoutDirection 变成镜像。请注意,layoutDirection 属性的实际值将保持不变;定位器和视图的有效布局方向考虑了镜像,可从effectiveLayoutDirection 属性中读取。
// by default child items are positioned from left to right
Row {
Child {}
Child {}
}
// position child items from right to left
Row {
layoutDirection: Qt.RightToLeft
Child {}
Child {}
}
// position child items from left to right
Row {
LayoutMirroring.enabled: true
layoutDirection: Qt.RightToLeft
Child {}
Child {}
}
布局镜像
所附的LayoutMirroring 属性可方便地为现有的从左到右Qt Quick 应用程序提供从右到左的支持。它反映了Item anchors 的行为、定位器和模型视图的布局方向,以及 QML 文本类型的显式文本对齐方式。
您可以为特定的Item 启用布局镜像:
Item {
height: 50; width: 150
LayoutMirroring.enabled: true
anchors.left: parent.left // anchor left becomes right
Row {
// items flow from left to right (as per default)
Child {}
Child {}
Child {}
}
}
或设置所有子类型也继承布局方向:
Item {
height: 50; width: 150
LayoutMirroring.enabled: true
LayoutMirroring.childrenInherit: true
anchors.left: parent.left // anchor left becomes right
Row {
// setting childrenInherit in the parent causes these
// items to flow from right to left instead
Child {}
Child {}
Child {}
}
}
以这种方式应用镜像不会改变相关锚点、layoutDirection 或horizontalAlignment 属性的实际值。单独的只读属性effectiveLayoutDirection 可用于查询定位器和模型视图的有效布局方向,并将镜像考虑在内。同样,Text 、TextInput 和TextEdit 类型也获得了只读属性effectiveHorizontalAlignment ,用于查询文本的有效视觉对齐方式。
请注意,使用x 属性值(而不是锚点或定位器类型)定义的应用程序布局和动画不受LayoutMirroring 附加属性的影响。因此,为这些类型的布局添加从右向左的支持可能需要对应用程序进行一些代码修改,尤其是在同时依赖锚点和基于 x 坐标定位的视图中。以下是使用LayoutMirroring attached 属性对使用x 坐标定位的项目应用镜像的一种方法:
Rectangle {
color: "black"
height: 50; width: 50
x: mirror(10)
function mirror(value) {
return LayoutMirroring.enabled ? (parent.width - width - value) : value;
}
}
并非所有布局都需要镜像。在某些情况下,将视觉类型定位在屏幕右侧是为了提高单手操作的效率,因为大多数人都是右撇子,而不是因为阅读方向。如果子类型不受镜像影响,请将该类型的LayoutMirroring.enabled 属性设置为 false。
Qt Quick 镜像是为开发动画、流畅的用户界面而设计的。在镜像应用程序时,请务必测试动画和过渡效果是否与预期一致。如果您没有资源为应用程序添加从右向左的支持,那么最好保持应用程序布局左对齐,并确保文本翻译和对齐正确。
镜像图标
(这适用于Image 、BorderImage 和AnimatedImage 类型)。
大多数图像不需要镜像,但某些方向性图标(如箭头)可能需要镜像。这些图标的绘制可以通过专用的mirror 属性进行镜像:
Image {
source: "arrow.png"
mirror: true
}
默认布局方向
使用Qt.application.layoutDirection 属性可查询应用程序的活动布局方向。该属性继承于QGuiApplication::layoutDirection(),后者根据活动语言翻译文件确定布局方向。
要定义特定语言的布局方向,请将上下文QGuiApplication 中的专用字符串字面QT_LAYOUT_DIRECTION 声明为LTR 或RTL 。
首先,在 QML 源代码中引入这一行:
qsTr("QT_LAYOUT_DIRECTION","QGuiApplication");
然后使用Using lupdate生成翻译源文件。
这将在翻译文件中添加以下声明,您可以在其中输入LTR 或RTL 作为 locale 的翻译。
接下来,在应用程序的根 QML 组件中添加以下绑定:
LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft
LayoutMirroring.childrenInherit: true
第一个绑定确保在设置从右向左的本地化时,用户界面将被适当镜像。第二个绑定确保根组件的子项也会尊重镜像。
您可以使用编译好的翻译文件运行Qt Quick 应用程序,测试布局方向是否符合预期:
qml myapp.qml -translation myapp.qm
您可以调用静态函数QGuiApplication::setLayoutDirection() 测试应用程序的布局方向是否从右向左:
QGuiApplication app(argc, argv);
app.setLayoutDirection(Qt::RightToLeft);