当前位置: 首页 > article >正文

Android切换语言不退出App

1.需求

实现用户选择语言(未点击下一步),更新当前界面UI,点击下一步后,更新App的语言,并进行保存。

实现目标:

1.设置App的语言,本地进行保存

2.updateResources更新本地语言配置

2.实现代码

1.LanguageManager

object LanguageManager {
    private const val PREFS_NAME = "settings"
    private const val LANGUAGE_KEY = "language"

    fun setLanguage(context: Context, language: String) {
        // 保存语言到 SharedPreferences
        val sharedPreferences = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
        sharedPreferences.edit().putString(LANGUAGE_KEY, language).apply()

        // 更新资源
        updateResources(context, language)
    }

    fun getSavedLanguage(context: Context): String {
        // 如果没有保存语言,默认使用系统语言
        val sharedPreferences = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
        return sharedPreferences.getString(LANGUAGE_KEY, Locale.getDefault().language) ?: Locale.getDefault().language
    }

    fun applyLanguage(context: Context): Context {
        // 获取保存的语言并更新 Context
        val language = getSavedLanguage(context)
        return updateResources(context, language)
    }

    private fun updateResources(context: Context, language: String): Context {
        val locale = Locale(language)
        Locale.setDefault(locale)

        val configuration = Configuration(context.resources.configuration)
        configuration.setLocale(locale)

        return context.createConfigurationContext(configuration)
    }
}

2.所有的基类进行设置,记得application在manifest应用

class MyApplication : Application() {
    override fun attachBaseContext(base: Context) {
        // 应用保存的语言
        super.attachBaseContext(LanguageManager.applyLanguage(base))
    }

    override fun onConfigurationChanged(newConfig: Configuration) {
        super.onConfigurationChanged(newConfig)
        // 当配置改变时(如系统语言切换),重新应用用户选择的语言
        LanguageManager.applyLanguage(this)
    }
}

BaseActivity

所有 Activity 自动应用语言配置:

open class BaseActivity : AppCompatActivity() {
    override fun attachBaseContext(newBase: Context) {
        // 为每个 Activity 更新语言配置
        super.attachBaseContext(LanguageManager.applyLanguage(newBase))
    }
}
open class BaseFragment : Fragment() {
    override fun onAttach(context: Context) {
        super.onAttach(LanguageManager.applyLanguage(context))  // 在这里更新语言
    }
}

3.为什么还要在 Activity 里设置语言?

通常,在 ActivityFragment 中设置语言是为了在运行时动态更新语言,尤其是当用户切换语言后,某些界面可能需要重新加载来反映新的语言设置。

关键点:

  1. Application 中设置语言:可以在应用启动时统一设置默认语言,确保语言配置在整个应用中生效。
  2. ActivityFragment 中设置语言:可以在用户选择语言并希望立即看到语言更改时,确保当前 ActivityFragment 界面更新。

4.在当前页动态修改语言设置,动态修改文案,但是不点击下一步时,不保存语言选择。

   private fun updateLanguage(languageCode: String) {
        LogUtils.e("updateLanguage", languageCode)
        val finalCode: String = languageCode
        val locale =if (languageCode == AppConstants.ZH_HANS) {
            Locale("zh","CN")
        } else if (languageCode == AppConstants.ZH_HANT) {
            Locale("zh","TW")
        } else Locale(finalCode)
        Locale.setDefault(locale)  // 设置默认语言
        val config = Configuration(resources.configuration)
        config.setLocale(locale)  // 修改当前界面语言
        // 创建新的 Context,并应用新的 Configuration
        val localizedContext = createConfigurationContext(config)
        // 将新的 Context 应用于当前页面的 UI
        val resources = localizedContext.resources
        val displayMetrics = resources.displayMetrics
        resources.updateConfiguration(config, displayMetrics)
        // 使用新的语言设置刷新当前界面
        initData(localizedContext)  //界面将刷新以应用新的语言
    }

5.其余关键点

1.既然只刷新当前UI,就得生成新的context

localizedContext = createConfigurationContext(config)

2.initData里面就是数据赋值渲染UI,如果调用Activity的recreate方法会闪退,别调用。

6.保存设置退出App

需求:点击语言后,保存语言设置,并且退出App

//点击事件
binding.langCl.setOnClickListener {
            diaLog = LanguageBottomSheetFragment { selectedLanguage ->
                lifecycleScope.launch {
                    LogUtils.e("onLanguageSelected", selectedLanguage)
                    val saveSuccess = saveLanguageSuspend(requireContext(), selectedLanguage)
                    if (saveSuccess) {
                        diaLog?.binding?.root?.isEnabled = false
                        diaLog?.dismiss() // 关闭弹窗
                        restartApp()
                    } else {
                        LogUtils.e("saveLanguage", "Failed to save language")
                    }
                }
            }
            diaLog?.show(parentFragmentManager, "LanguageBottomSheet")
//             VIPBottomSheetFragment().show(parentFragmentManager, "VIPBottomSheet")
        }


//保证保存成功
   suspend fun saveLanguageSuspend(context: Context, language: String): Boolean {
        return suspendCancellableCoroutine { continuation ->
            val sharedPreferences =
                context.getSharedPreferences(BaseApp.PREFS_NAME, Context.MODE_PRIVATE)
            val success = sharedPreferences.edit().putString(LANGUAGE_KEY, language).commit()
            continuation.resume(success)
        }
    }

tips:

1、**suspendCancellableCoroutine** 是 Kotlin 中用于将回调或异步操作转化为挂起函数的工具。它是挂起函数的一部分,可以与协程一起工作,并且能够在协程上下文被取消时进行适当的处理。

2、continuation.resume(success) 将保存结果恢复给挂起函数调用者。


http://www.kler.cn/a/502211.html

相关文章:

  • 【某大型互联网企业】软件测试面试经验分享(1 ~ 3年)
  • springboot vue uniapp 仿小红书 1:1 还原 (含源码演示)
  • 初学spring 框架(了解spring框架的技术背景,核心体现,入门案例)
  • plane开源的自托管项目
  • js:正则表达式
  • git提交
  • 一个可以把玩的针对WebSocket分段的处理方案
  • 浅谈云计算07 | 云安全机制
  • 蓝桥杯历届真题 # 数字诗意(C++,Java)
  • React面试常见题目
  • C++中 为什么要把基类指针指向子类对象?
  • STM32 FreeRTOS的任务创建和删除
  • 2_CSS3 背景 --[CSS3 进阶之路]
  • vue集成导出 txt文本文档 和 excel文档 的方法
  • jsdom爬虫程序中eBay主页内容爬取的异步处理
  • 从epoll事件的视角探讨TCP:三次握手、四次挥手、应用层与传输层之间的联系
  • 【论文笔记】Sign Language Video Retrieval with Free-Form Textual Queries
  • IDEA的Git界面(ALT+9)log选项不显示问题小记
  • 基于Java的推箱子游戏设计与实现
  • 31_搭建Redis分片集群
  • React中Fiber树构建过程详解——react中render一个App组件(包含子组件)的流程详解
  • 深度学习中的常见初始化方法:原理、应用与比较
  • C语言结构体如何实现位段
  • async++源码阅读——task模块
  • 【HM-React】08. Layout模块
  • 树状数组与线段树简单讲解与习题