在不重启应用的情况下丝滑实现原生语言切换和灰色主题模式切换
文章目录
- 在不重启应用的情况下丝滑实现原生语言切换和灰色主题模式切换
- 一、背景描述
- 效果图
- 二、原生语言切换
- 三、灰色模式
- 四、说明
一、背景描述
目前大部分的app在实现灰色模式和语言切换的时候都需要重新启动应用或者重新打开这个Activity,这让我感觉体验不好,所以尝试用的新的方法来实现这2个功能,达到丝滑的效果
效果图
二、原生语言切换
首先要说的是不用重启的核心的API:
ActivityCompat.recreate(activity)
:可以丝滑的达到重建,不过这个API使用条件是Android≥ 26
接下来说明一下具体的实现过程和一些核心的API
/*修改应用内语言设置*/
fun changeLanguage(context: Context, newLocale: Locale = Locale.ROOT) {
setAppLanguage(context, newLocale)
saveLanguageSetting(context, newLocale)
ActivityCompat.recreate(context.asActivity)
}
/*设置语言*/
private fun setAppLanguage(context: Context, locale: Locale) {
val resources = context.resources
val metrics = resources.displayMetrics
val configuration = resources.configuration
//Android 7.0以上的方法
if (VERSION.SDK_INT >= 24) {
configuration.setLocale(locale)
configuration.setLocales(LocaleList(locale))
context.createConfigurationContext(configuration)
//实测,updateConfiguration这个方法虽然很多博主说是版本不适用
//但是我的生产环境androidX+Android Q环境下,必须加上这一句,才可以通过重启App来切换语言
resources.updateConfiguration(configuration, metrics)
} else if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1) {
//Android 4.1 以上方法
configuration.setLocale(locale)
resources.updateConfiguration(configuration, metrics)
} else {
configuration.locale = locale
resources.updateConfiguration(configuration, metrics)
}
}
/*获取应用的语言*/
fun getAppLocale(context: Context): Locale {
val local: Locale = if (VERSION.SDK_INT >= VERSION_CODES.N) {
context.resources.configuration.locales[0]
} else {
context.resources.configuration.locale
}
return local
}
部分其他代码
fun saveLanguageSetting(context: Context, locale: Locale) {
SPUtils.put(context, SP_LANGUAGE, locale.language)
SPUtils.put(context, SP_COUNTRY, locale.country)
}
fun attachBaseContext(context: Context): Context {
val language = SPUtils.get(context, SP_LANGUAGE, "") as String
val country = SPUtils.get(context, SP_COUNTRY, "") as String
if (!TextUtils.isEmpty(language)) { //只比较语言
//强制修改应用语言
if (!isSameWithSetting(context)) {
val locale = Locale(language, country)
setAppLanguage(context, locale)
}
}
return context
}
需要注意的事,因为切换暗黑模式、横竖屏等都会导致丢失配置,所以我们还需要以下代码
override fun onNightModeChanged(mode: Int) {
super.onNightModeChanged(mode)
LanguageKit.attachBaseContext(this)
}
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
LanguageKit.attachBaseContext(this)
}
override fun attachBaseContext(newBase: Context?) {
super.attachBaseContext(newBase)
LanguageKit.attachBaseContext(this)
}
}
//可能不全,需要自己去实现更多的情况
ActivityCompat.recreate(activity)
是单个重建,所以要注意通知全部已经创建的Activity
进行重新创建,这里我就不写我的实现了,这里实现的方案太多
三、灰色模式
首先还是核心的API的说明:
原理就是给Activity
的decorView
设置一个灰色图层,而且没有版本限制,所有Activity都是一样的改法,不需要去重新启动,达到丝滑的全局切换,最好写在base,
fun FragmentActivity.grayThemChange(isGrayTheme:Boolean){
val decorView = window?.decorView
val isMourn = (decorView?.getTag(R.id.isGrayTheme) as? Boolean )?:false
if (!isMourn){
if (isGrayTheme){
decorView?.setTag(R.id.isGrayTheme,true)
decorView?.setLayerType(View.LAYER_TYPE_HARDWARE, getSatPaint(0f))
}
}else{
if (!isGrayTheme){
decorView?.setTag(R.id.isGrayTheme,false)
decorView?.setLayerType(View.LAYER_TYPE_NONE, null)
}
}
}
fun getSatPaint(sat:Float = 1f): Paint {
mColorMatrix.setSaturation(sat)
mPaint.colorFilter = ColorMatrixColorFilter(mColorMatrix)
return mPaint
}
其他代码就不一一描述
四、说明
文章更多的是一种实现思路,具体实现需要根据实际情况开发
比如第一个原生语言切换虽然可以丝滑实现,但是要求版本是 android >= 26