You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin中替代recreate()更新UI与字符串的更优方案

替代recreate()实现UI流畅更新的方案

一、深色模式切换:无需重建Activity的主题更新

不用调用recreate(),直接更新当前Activity的主题并遍历视图树刷新控件样式,配合过渡动画实现流畅切换:

  1. 核心更新逻辑
private fun updateDarkMode(isDarkMode: Boolean) {
    // 切换当前Activity的主题
    val targetTheme = if (isDarkMode) R.style.Theme_App_Dark else R.style.Theme_App_Light
    setTheme(targetTheme)
    
    // 递归刷新所有子视图的样式
    refreshViewTheme(findViewById(android.R.id.content))
}

private fun refreshViewTheme(view: View) {
    // 为当前视图重新应用主题样式
    view.context.theme.applyStyle(view.context.themeResId, true)
    
    // 遍历ViewGroup的子视图
    if (view is ViewGroup) {
        for (i in 0 until view.childCount) {
            refreshViewTheme(view.getChildAt(i))
        }
    }
    
    // 针对文本控件单独处理颜色(部分控件可能需要单独适配)
    if (view is TextView) {
        val typedValue = TypedValue()
        view.context.theme.resolveAttribute(android.R.attr.textColorPrimary, typedValue, true)
        view.setTextColor(typedValue.data)
    }
}
  1. 添加过渡动画
    用TransitionManager实现淡入淡出效果,避免切换突兀:
// 在调用主题更新前启动过渡
TransitionManager.beginDelayedTransition(findViewById(android.R.id.content), Fade())
updateDarkMode(isDarkMode)

二、语言切换:直接更新控件文本资源

通过修改Configuration并创建新Context,递归刷新所有控件的文本内容,无需重建Activity:

  1. 核心语言更新逻辑
private fun updateAppLanguage(targetLocale: Locale) {
    val config = resources.configuration
    config.setLocale(targetLocale)
    
    // 创建适配新语言的Context
    val newContext = createConfigurationContext(config)
    // 更新当前Activity的资源配置
    resources.updateConfiguration(config, resources.displayMetrics)
    
    // 递归刷新所有控件的文本
    refreshViewsText(findViewById(android.R.id.content), newContext)
}

private fun refreshViewsText(view: View, context: Context) {
    // 更新TextView及子类(Button、EditText等)的文本
    if (view is TextView) {
        // 通过文本内容反向获取资源ID(需确保文本是直接引用字符串资源)
        val textResId = try {
            resources.getIdentifier(view.text.toString(), "string", packageName)
        } catch (e: Exception) {
            0
        }
        if (textResId != 0) {
            view.text = context.getString(textResId)
        }
    }
    
    // 遍历ViewGroup的子视图
    if (view is ViewGroup) {
        for (i in 0 until view.childCount) {
            refreshViewsText(view.getChildAt(i), context)
        }
    }
}

额外注意事项

  • 复杂控件适配:对于RecyclerView、ViewPager等列表类控件,刷新后需调用adapter.notifyDataSetChanged()或重新绑定页面视图,确保内容同步更新。
  • 持久化设置:将深色模式、语言配置保存在SharedPreferences中,在Application或启动Activity的onCreate()方法中提前加载配置,保证应用重启后设置生效。

内容的提问来源于stack exchange,提问作者mohammed_sajid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 02:48:19