当前位置: 首页 > 知识库问答 >
问题:

使用JetPack Compose更改Android语言

楚鸿波
2023-03-14

我正在尝试使用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查看工作示例(没有按钮或文本字段)

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

共有1个答案

红富
2023-03-14

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

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

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

以下代码是我从您的Github项目中获取并添加了一个按钮的代码。请注意字符串资源id是如何可变的,并且这种可变状态在Text中使用:

@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中的资源,如上所示。

即使上面的解决方案有效,我也不推荐使用它。大多数应用程序会有很多语言相关的组件,并且必须为每个资源字符串创建一个可变的状态会很痛苦。一个更好的解决方案是,每当语言发生变化时,强制重新编写整个应用程序。由于只合成应用程序通常只是一个活动,它将导致整个应用程序重新合成。这将确保所有屏幕重组并强制所有文本组件重组,而不需要每个组件都有可变状态。有不同的方法可以让你的应用程序重组整个UI树。不幸的是,Compose不包含一个API,让您从头开始重新编写整个树,所以唯一真正的解决方案是重新启动应用程序。

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

https://github.com/JohannBlake/Jetmagic

 类似资料:
  • 为应用程序创建多语言支持,可以更改应用程序中的语言设置。 至于现在,一切都适用于英语、西班牙语、法语、俄语,但不适用于印地语和汉语。 1) 我以原始语言指定语言名称,但在应用程序中指定,而不是हिन्दी 我能看到“印地语”。 \res \ values hi \数组。xml 2) 选择“印地语”后结束-实际上选择了默认值(英语) \res\values hi\strings。xml .... 在

  • 问题内容: 我发现了只在Android N设备上才能复制的真正奇怪的错误。 在浏览我的应用程序时,可以更改语言。这是更改它的代码。 该代码在我的巡回活动(带电话)中效果很好,但是在接下来的所有活动中,所有String资源都是错误的。屏幕旋转将其修复。我该怎么办?我应该以其他方式更改Android N的语言环境还是仅仅是系统错误? PS这是我发现的。第一次启动MainActivity时(在​​我的旅

  • 我正在尝试在运行时更改语言。它在API29(android版本10)上运行得很好。我需要使它在牛轧糖7.1.1(API 25)上工作。这是一场噩梦。如果我必须通过设置更改设备语言..,它可以工作。我可以看到正确的drawable和字符串(strings.xml) 我的目标是使语言切换在运行时发生。 我正在onResume()中调用activity.recreate()。屏幕变黑。我得到一个异常,它

  • 如果用户选择任何语言的应用程序更改,language.but我的应用程序内容是从json检索数据api.how改变它? 在此处输入图像描述 } } 在此处输入图像描述

  • 问题内容: 我使用记录的日期选择在这里。 但是,没有直接选项允许更改语言,默认情况下为 英语 。 我找到了不带angular指令提供的小部件的文档,它提供了一种实现它的好方法: http://bootstrap- datepicker.readthedocs.org/en/latest/i18n.html 有没有一种简便的方法来避免调整原始指令的源代码来进行更改? 问题答案: 如果您使用的是Dat

  • 问题内容: 我想更改应用程序的语言,在API 26之前可以正常使用。 对于api> 25我放在了前面,但没有任何变化。 该文档不解释太多关于这一点。 问题答案: 我遇到了同样的问题:自Android 8.0+起,我的应用程序的某些部分不再更改其语言。更新应用程序和活动上下文对我有帮助。这是MainActivity函数的示例: