ITmob-Ly
发布于 2023-07-11 / 123 阅读
0

Android View 和 Jetpack Compose 中怎样支持 RTL 图标/从右到左图标/镜像图标?

Google Fonts - Material icons

介绍

系统会按照从右到左 (RTL) 的方向阅读阿拉伯语和希伯来语等语言。界面镜像 RTL 显示时,某些图标也应该被镜像。例如:ActionBar 中返回键向左,RTL 时应向右

默认情况下,在 Android 中,当布局方向是镜像时,不会镜像图标。您可以根据需要专门镜像相应的图标。

本文将分别介绍使用 Android View 和 Jetpack Compose 开发时怎样支持 RTL 图标,当布局方向为 RTL 时自动镜像图标。

1. Android View 支持 RTL 图标

使用 Android View (传统的视图/View)开发时有多种方式可以实现对 RTL 图标的支持。

1.1 Android 4.4 之前的版本

Android 4.4(API 级别:19)以前的 Android 版本中,如果您的应用包含应针对从右向左布局扭转其水平方向的图像,必须在 drawables-ldrtl 资源目录中添加镜像,这个目录中的资源将仅用于 RTL 语言。

1.2 通过 autoMirrored/setAutoMirrored()

Android 4.4(API 级别:19)或更高版本可以通过在 Drawable 资源上启用 [autoMirrored](https://developer.android.com/reference/android/R.attr?hl=zh-cn#autoMirrored) 属性,或通过 [setAutoMirrored()](https://developer.android.com/reference/android/graphics/drawable/Drawable?hl=zh-cn#setAutoMirrored(boolean)) 方法,系统可以自动为您进行镜像。启用后,当布局方向为从右到左时,[Drawable](https://developer.android.com/reference/android/graphics/drawable/Drawable?hl=zh-cn) 将自动镜像。

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:autoMirrored="true"
    android:height="24dp"
    android:tint="#77A9F3"
    android:viewportHeight="24"
    android:viewportWidth="24"
    android:width="24dp">
    <path android:fillColor="@android:color/white" android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z"/>
</vector>

1.3 通过 layout-ldrtl 目录

如果无法使用自动镜像或提供备用可绘制资源,ImageViewscaleX 属性还可用于镜像可绘制对象可以在 res/layout-ldrtl 目录中提供特定用于 RTL 的布局。

在布局文件中镜像 ImageView

<ImageView
    android:id="@+id/my_icon"
    android:layout_width="60dp"
    android:layout_height="60dp"
    android:scaleX="-1" />

1.4 通过编程方式实现镜像。

使用 getLayoutDirection 手动检查布局方向:

if (ViewCompat.getLayoutDirection(view) == ViewCompat.LAYOUT_DIRECTION_RTL) {
  // TODO
}

以编程方式镜像 ImageView 的内容:

imageView.setScaleX(-1);

2. Jetpack Compose 支持 RTL 图标

当布局方向是镜像时,Jetpack Compose 也不会自动镜像图标,如果我们使用 Drawable 资源作为图标时,可以像上面提到的使用 autoMirrored 属性实现图标自动镜像

但是如果我们使用 ImageVector 作为图标时,我们常用 material-iconsmaterial-icons-extended 库定义的图标资源,这两个库中定义的 ImageVector 图标并没有设置 autoMirrored 属性,不能实现图标自动镜像,需要使用 Modifier.scale() 来镜像图标

使用 Compose 的 icons 资源时,请注意:这里使用的 material-iconsmaterial-icons-extended 的版本是 **1.3.1,**未来官方的库如果增加了镜像图标的默认实现,就不需要自己实现了。

  1. 使用 scale 镜像图标:
IconButton(onClick = { /*TODO*/ }) {
    Icon(
        modifier = Modifier.scale(scaleX = -1f, scaleY = 1f),
        imageVector = Icons.Default.ArrowBack,
        contentDescription = "content description - https://itmob.cn",
    )
}

  1. 如果想更方便的实现 ImageVector 图标的镜像,可以创建一个 Modifier 的扩展函数来完成:
@Stable
fun Modifier.autoMirrored(): Modifier {
    return if (Locale.getDefault().layoutDirection == LayoutDirection.RTL)
        this.scale(scaleX = -1f, scaleY = 1f)
    else
        this
}

用法:

IconButton(onClick = { /*TODO*/ }) {
    Icon(
        modifier = Modifier.mirror(),
        imageVector = Icons.Default.ArrowBack,
        contentDescription = "content description - https://itmob.cn"
    )
}

Set screen layout direction to RTL in Jetpack Compose