使用 JetPack Compose 更改 Android 语言

2024-03-31

我正在尝试使用 jetpack compose 功能更改应用程序的区域设置,如下所示

  @Composable
 fun SetLanguage(position: Int) {
    val locale = Locale(
        when (position) {
            0 -> "ar"
            1 -> "en"
            2 -> "fr"
            else -> {
                "ar"
            }
        }
    )
    Locale.setDefault(locale)
    val configuration = LocalConfiguration.current
    configuration.setLocale(locale)
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1)
        configuration.setLocale(locale)
    else
        configuration.locale = locale
    var resources = LocalContext.current.resources
    resources.updateConfiguration(configuration, resources.displayMetrics)

}

您可以在此处查看工作示例(没有按钮或文本字段)https://github.com/MakeItEasyDev/Jetpack-Compose-Multi-Language-Support https://github.com/MakeItEasyDev/Jetpack-Compose-Multi-Language-Support

但问题是不适用于 OutlinedTextField 或 Button,因为调用此函数时它们不会改变,即使 rightToLeft 支持也不起作用,而且我找不到解决此问题的良好替代方案,因为我无法在项目中重新创建活动


许多开发人员在开始使用 Compose 时遇到的问题是相信当发生重组时,可组合项中的所有内容都会被重组。这不是真的。 Compose 会查看可组合签名并尝试确定自上次调用以来是否有任何更改。仅当参数values更改将调用该函数。在您在 Github 上发布的源代码中,它不包含用于演示问题的按钮或大纲文本字段,因此我添加了一个。当您添加这样的按钮时:

Button(onClick = {}) {
     Text("Do Something")
}

仅当初始组合发生时才会调用按钮内部的文本可组合项。但是当重新组合 Button 时,Text 不会被重新组合,因为 Button 函数中的最后一个参数没有改变。 Lambda 函数不会改变。对于您的情况,更改语言确实会启动按钮的重新组合,但由于最后一个参数不会更改,因此 lambda 内部的内容(在本例中为 Text 可组合项)将永远不会被调用。为了解决这个问题,一种解决方案是使 Text 可组合项使用的字符串资源可变。任何可变的内容都会自动导致任何使用它的可组合项进行重组。

下面的代码是我从你的 Github 项目中获取的并添加了一个按钮。请注意如何使字符串资源 id 变得可变,并且此可变状态在文本中使用:

@Composable
fun LanguageContentPortrait(
    selectedPosition: Int,
    onLanguageSelected: (Int) -> Unit
) {
    val buttonTextResId by remember { mutableStateOf(R.string.hello) }

    CompositionLocalProvider(
        LocalLayoutDirection provides
                if (LocalConfiguration.current.layoutDirection == LayoutDirection.Rtl.ordinal)
                    LayoutDirection.Rtl
                else LayoutDirection.Ltr
    ) {
        Column(
            modifier = Modifier
                .fillMaxSize()
                .padding(16.dp),
            horizontalAlignment = Alignment.CenterHorizontally
        ) {

            Spacer(modifier = Modifier.height(100.dp))
            ToggleGroup(selectedPosition = selectedPosition, onClick = onLanguageSelected)
            Spacer(modifier = Modifier.height(60.dp))
            Column(
                modifier = Modifier.fillMaxSize(),
                horizontalAlignment = Alignment.CenterHorizontally,
                verticalArrangement = Arrangement.Center
            ) {
                Text(
                    text = stringResource(id = R.string.content),
                    modifier = Modifier.fillMaxSize(),
                    textAlign = TextAlign.Center
                )

                Button(onClick = {}) {
                    Text(stringResource(buttonTextResId))
                }
            }
        }
    }
}

因此,在任何地方使用尾随 lambda 表达式(包括单击事件处理程序)并且需要进行与语言相关的更改时,您都需要向这些 lambda 内的资源添加可变状态,如上所示。

尽管上述解决方案有效,但我不建议使用它。大多数应用程序都会有很多依赖于语言的组件,并且必须为每个资源字符串创建可变状态将是一件痛苦的事情。更好的解决方案是在语言发生变化时强制整个应用程序重新组合。由于仅 Compose 应用程序通常只是一个 Activity,因此它会导致整个应用程序重新组合。这将确保所有屏幕重新组合并强制所有文本可组合项重新组合,而无需每个屏幕都具有可变状态。您可以通过多种方式强制应用程序重构整个 UI 树。不幸的是,Compose 不包含可让您从头开始重构整个树的 API,因此唯一真正的解决方案是重新启动应用程序。

由于您的应用程序旨在处理设备配置更改(例如语言更改),因此您可能需要查看我开发的专门用于处理设备配置更改的 Compose 框架。它的名字叫Jetmagic。它不仅处理语言更改,还处理所有其他更改,例如屏幕方向、屏幕尺寸、屏幕密度以及与旧的基于视图的系统一起使用的所有其他配置限定符。 Jetmagic 允许您将可组合项视为资源,而不仅仅是一堆函数,并且它处理它们的方式与在基于视图的系统下使用相同算法处理 xml 资源的方式完全相同。包含的示例应用程序还展示了如何更改设备的系统语言(在 Android 的设置下)或通过以编程方式更改语言,使您的可组合 UI 重新组合以正确的语言呈现内容:

https://github.com/JohannBlake/Jetmagic https://github.com/JohannBlake/Jetmagic

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 JetPack Compose 更改 Android 语言 的相关文章

  • 已发布的 Flutter 应用程序在启动时崩溃

    编辑 此问题的解决方案是将您的 flutter 版本升级到较新的 dev 版本 then 1 7 0 您还可以上传单独的 APK 版本 但我个人不喜欢这个选项 请确保您没有从 flutter github 开发存储库下载 错误的构建 因为那
  • 在 Android 中创建和使用 9 补丁图像

    我最近听说了 9 补丁图像 我知道它是 9 平铺的并且是可拉伸的 我想了解更多 如何创建 9 块图像 有什么工具吗 我可以通过 AndroidSDK 或代码创建它吗 9 patch 相对于普通 png 的主要优点 它是否可以根据屏幕动态 自
  • 是否可以使用最新的 APP_PLATFORM,同时仍保持向后兼容性?

    这是我的 Application mk APP ABI armeabi v7a APP PLATFORM android 16 APP OPTIM release APP STL gnustl static APP CPPFLAGS std
  • 如何检测和管理来电(Android)?

    我想创建一个应用程序 可以检测来电并在一定数量的蜂鸣声 响铃 后启动我的自定义活动 我的意思是在 2 或 3 或 5 声蜂鸣声 响铃 后我的activity被触发 我该怎么做 Thanks 我认为您无法计算自来电开始以来电话响了多少次 无法
  • Android 上的 Firebase:如何检查 Firebase 身份验证失败原因?

    我在 Android 上使用 Firebase 和 Firebase Auth 功能 I try FirebaseAuth signInWithEmailAndPassword如果失败 我想知道为什么登录过程失败 The signInWit
  • 如何使用 adb 在设备上安装现有的 Android 应用程序?

    在开发过程中 我使用类似的东西 adb s 192 168 1 77 5555 uninstall com myApp app adb s 192 168 1 77 5555 install path to android debug ap
  • SQLite (Android):使用 ORDER BY 更新查询

    Android SQLite 我想要在 myTable 中的其他行之间插入行在android中使用SQLite 为此 我尝试增加从第 3 行开始的所有行的 id 这样 我就可以在位置 3 处插入新行 myTable 的主键是列 id 表中没
  • 使用 Android 播放任意音调

    有没有办法让Android发出任意频率的声音 意思是 我不想预先录制声音文件 我环顾四周 音调发生器 http developer android com reference android media ToneGenerator html
  • android 确定设备是否采用从右到左的语言/布局

    有没有办法确定设备是否使用从右到左的语言 例如阿拉伯语 而不是从左到右的语言 英语 与较旧的 API 级别 低至 10 兼容的东西是必要的 SOLUTION 我最终在接受的答案中使用了 xml 方法 接下来 我还添加了此处指示的代码 以应对
  • 如何从android获取应用程序安装时间

    我尝试了一些方法 但没有成功 请帮助我 PackageManager pm context getPackageManager ApplicationInfo appInfo pm getApplicationInfo app packag
  • Integer.parseInt("0x1F60A") 以 NumberformatException 结束

    我尝试从数据库中获取长字符串内的表情符号代码 格式如下 0x1F60A 所以我可以访问代码 但它将是String 起初 我尝试通过执行以下操作来转换变量tv setText beforeEmo getEmijoByUnicode int e
  • Kotlin 未解决的参考:CLI 上 gradle 的 println

    放一个printlnkotlin 函数返回之前的语句会崩溃 堆栈跟踪 thufir dur NetBeansProjects kotlin thufir dur NetBeansProjects kotlin gradle clean bu
  • 从手机访问本地主机[关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 help reopen questions 我正在使用
  • android 中camera.setParameters 失败

    我已将相机功能包含在我的应用程序中 我还在市场上推出了该应用程序 我从一位用户那里收到一条错误消息 称他在打开相机时遇到错误 我已经在 2 1 的设备上测试了该应用程序 我从用户那里得到的错误是使用 Nexus One 它主要运行 2 2
  • 不显示 WRITE_EXTERNAL_STORAGE 的权限对话框

    I want to download a file using DownloadManager And DownloadManager wants to WRITE EXTERNAL STORAGE permission I have in
  • Android:确定 2.2 及更高版本上的摄像头数量

    我的应用程序需要在 Android 2 2 及更高版本上运行 我需要一种方法来确定可用摄像机的数量 有很多帖子解决了这个问题 但我找不到一个有效的 一种解决方案是简单地检测操作系统版本 任何 2 2 版本的设备都仅限于 1 个摄像头 即使该
  • Android - iphone 风格 tabhost [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 更改Android菜单的背景颜色[重复]

    这个问题在这里已经有答案了 我正在尝试将标准浅灰色更改为浅绿色 似乎没有一个简单的方法可以做到这一点 例如 通过 Android 主题 但我找到了一个解决方法 如本页所述 http tinyurl com 342dgn3 http tiny
  • 具有矢量可绘制的 ImageView 的 Resources$NotFoundException

    我遇到了崩溃 Resources NotFoundException用于在活动创建时绘制的矢量 21 日前崩溃 安卓工作室2 1 支持库24 0 0 Gradle插件2 1 0 目标SDK 23 最小SDK 15 buildTools版本
  • putFragment() - 片段 x 当前不在 FragmentManager 中

    上面的标题被问了很多次 但答案似乎与FragmentStatePagerAdapter这与我的问题无关 我正在使用该方法putFragment Bundle String Fragment 直接地 The 安卓文档 http develop

随机推荐