安卓多语言设置,深渊巨坑,适配7.0以上,并且解决因WebView产生的问题

54 篇文章 2 订阅
46 篇文章 1 订阅

前言

安卓的多语言设置配置中strings.xml我就不说怎么弄了,主要说一下后续遇到的坑

正文

上个月接到需求,要给app内添加多语言设置,我心想没啥难的,配置一下strings.xml,加个修改的页面并保存到本地就ok了

然后过了一阵,发现坑真多,然后我写了个工具类,如下:

/**
 * creator: lt  2019/7/29--16:36    lt.dygzs@qq.com
 * effect : 多语言管理类
 * warning:
 */
object LanguageManager {
    enum class LocaleEnum(val value: Int) {
        DEFAULT(0),//跟随系统
        CHINESE(1),//简体中文
        TRADITIONAL_CHINESE(2),//繁体中文
        ENGLISH(3),//英文
    }

    /**
     * 获取地区对应的enum
     */
    @JvmStatic
    fun getLocaleEnum(locale: Locale): LocaleEnum {
        return when {
            locale.language == Locale.SIMPLIFIED_CHINESE.language -> //中国文字
                if (locale.country == Locale.SIMPLIFIED_CHINESE.country || locale.country.isEmpty()) {
                    //简体
                    LanguageManager.LocaleEnum.CHINESE
                } else {
                    //其他就是繁体文字
                    LanguageManager.LocaleEnum.TRADITIONAL_CHINESE
                }
            locale.language == Locale.US.language -> //英文
                LanguageManager.LocaleEnum.ENGLISH
            else -> //其他就是默认的,使用系统语言
                LanguageManager.LocaleEnum.DEFAULT
        }
    }

    /**
     * 获取app当前的地区设置
     */
    @JvmStatic
    fun getAppLocale(): Locale {
        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            BaseApplication.getApp().resources.configuration.locales[0]
        } else {
            BaseApplication.getApp().resources.configuration.locale
        }
    }

    /**
     * 获取系统的地区设置
     */
    @JvmStatic
    fun getSystemLocale(): Locale {
        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            Resources.getSystem().configuration.locales[0]
        } else {
            Resources.getSystem().configuration.locale
        }
    }

    /**
     * 获取本地存储的地区设置
     */
    @JvmStatic
    fun getNativeLocale(): Locale {
        return when (SPUtil.readInt("setting", "locale", LanguageManager.LocaleEnum.DEFAULT.value)) {
            LanguageManager.LocaleEnum.CHINESE.value -> Locale.SIMPLIFIED_CHINESE
            LanguageManager.LocaleEnum.TRADITIONAL_CHINESE.value -> Locale.TRADITIONAL_CHINESE
            LanguageManager.LocaleEnum.ENGLISH.value -> Locale.US
            else -> getSystemLocale()
        }
    }

    /**
     * 保存地区设置到本地
     */
    @JvmStatic
    fun saveNativeLocale(localeEnum: LocaleEnum) {
        SPUtil.write("setting", "locale", localeEnum.value)
    }

    /**
     * 设置语言
     */
    @JvmStatic
    fun setLanguage(context: Context, locale: Locale) {
        val config = context.resources.configuration//获取配置
        config.locale = locale// 根据当前语言来判断,并更改当前语言
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            config.setLocale(locale)
        }// 根据当前语言来判断,并更改当前语言
        context.resources.updateConfiguration(config, context.resources.displayMetrics)//更新配置
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            context.createConfigurationContext(config)
        }//更新配置
    }

    /**
     * 初始化有WebView的Activity,必须在onCreate的super下面一行调用
     */
    @JvmStatic
    fun initWebViewActivity(activity: Activity) {
        WebView(activity).destroy()
        setLanguage(activity, getNativeLocale())
        setLanguage(BaseApplication.getApp(), getNativeLocale())
    }

    /**
     * 在BaseActivity的attachBaseContext方法中调用
     */
    @JvmStatic
    fun attachBaseContext(context: Context?): ContextWrapper {
        if (context != null)
            setLanguage(context, getNativeLocale())
        return ContextWrapper(context)
    }

}

使用有几个注意点:

1.初始化地点:

Application的onCreate()中调用一次

LanguageManager.setLanguage(this, LanguageManager.getNativeLocale())

然后在BaseActivity中调用如下:在页面初始化的时候设置一下语言(我之前没这样设置的时候华为手机没问题,但是vivo手机很大几率出现语言错乱,所以加上这个)

    override fun attachBaseContext(newBase: Context?) {
        super.attachBaseContext(LanguageManager.attachBaseContext(newBase))
    }

2.更改语言设置:

//根据设置传入用户选中的locale
LanguageManager.saveNativeLocale(LanguageManager.getLocaleEnum(locale))
LanguageManager.setLanguage(this, locale)
LanguageManager.setLanguage(BaseApplication.getApp(), locale)
recreate();//重新启动当前Activity来改变当前页面的语言

3.WebView的坑

我做完了前面的操作,工具类也封装好了,就在我以为完美的时候,现实再次给了我当头一棒,,,,Android7.0以上的WebView竟然会改变当前语言的设置???

然后查了一下,并参考Android N之后 Webview导致多语言切换失效的问题_android中webview切换多语言刷新问题-CSDN博客

加了个方法,用法如下:

在有用到WebView的页面内,在onCreate()内调用如下方法,即可解决这种问题
override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        LanguageManager.initWebViewActivity(this)//注意放在super的下面一行
        ............
}

 然后在Application的onCreate中的super.onCreate下调用以下代码

        try {
            new WebView(this).destroy();
        } catch (Exception e) {
            e.printStackTrace();
        }

然后就解决了,emmm方案近乎完美 /捂脸

对Kotlin或KMP感兴趣的同学可以进Q群 101786950

如果这篇文章对您有帮助的话

可以扫码请我喝瓶饮料或咖啡(如果对什么比较感兴趣可以在备注里写出来)

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值