1. 示例图
编辑
2.具体实现
如何实现上述示例,且不需要重新打开App
①自定义 MainApplication 实现 Application ,定义两个变量:
class MainApplication : Application() {
object GlobalDpData {
var language: String = ""
var defaultLanguage: String = "en"
}
override fun onCreate() {
defaultLanguage = Locale.getDefault().language
val cacheLanguage = "保存在手机App本地的切换后的语言,可用sp或文件实现"
language = if (cacheLanguage.isNullOrEmpty()) {
defaultLanguage
} else {
cacheLanguage
}
}
}
②在baseActivity中添加语言实现
override fun attachBaseContext(baseContext: Context) {
var language = MainApplication.GlobalDpData.language
if (language.isEmpty()) {
val default = MainApplication.GlobalDpData.defaultLanguage
language = "保存在手机App本地的切换后的语言,可用sp或文件实现"
}
// 创建一个ContextWrapper对象
val context = newWrap(baseContext, language)
// 将新的的Context设置给Activity
super.attachBaseContext(context)
}
/**
* 创建ContextWrapper对象,
*/
private fun newWrap(context: Context, language: String): ContextWrapper {
val configuration = context.resources.configuration
configuration.fontScale = 1f
val locale = Locale(language)
val localeList = LocaleList(locale)
LocaleList.setDefault(localeList)
configuration.setLocales(localeList)
return ContextWrapper(context.createConfigurationContext(configuration))
}
③在自定义语言实现Activty
设置语言实现的构造体
data class Language(val id: String,
val name: String,
var isSelected: Boolean = false)
id:即语言的id,比如英语"English",中文"简体中文",如 Language("English", "English", true)
数据变化的mutableStat List
private var languageList by mutableStateOf(listOf(Language("English", "English", true)))
companion object {
const val AUTO_TAG = "auto_tag"
}
// 选中的语言
private var checkLanguageID = ""
// 要保存到sp的语言
private var spLanguageID = ""
// 语言是否被选中
private var isCheck by mutableStateOf(true)
private var defaultID = "en"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
addLanguageList()
setContent {
SetShowView()
}
}
/**
* 初始化数据
*/
private fun addLanguageList() {
val autoKey = getString(R.string.xxx)
val mutableMap = mutableMapOf(
AUTO_TAG to false,
"English" to false,
"Deutsch" to false,
"简体中文" to false,
)
val stringKey = "保存在手机App本地的切换后的语言,可用sp或文件实现"
if (stringKey.isNullOrEmpty()) {
mutableMap[AUTO_TAG] = true
spLanguageID = AUTO_TAG
} else {
mutableMap[stringKey] = true
spLanguageID = stringKey
}
val mutableList: MutableList<Language> = mutableListOf()
for ((key, value) in mutableMap) {
if (key == AUTO_TAG) {
mutableList.add(Language(id = AUTO_TAG, name = autoKey, isSelected = value))
} else {
mutableList.add(Language(id = key, name = key, isSelected = value))
}
}
languageList = mutableList
}
/**
* 展示view
*/
@Composable
fun SetShowView() {
Column (
Modifier
.fillMaxSize()
.background(colorResource(id = R.color.xxx))
.padding(top = xx.dp)
) {
//标题
SetTitleView(
middleTitle = stringResource(id = R.string.xxx),
rightTitle = stringResource(id = R.string.xxx),
isClick = isCheck,
onClick = {
finishActivity()
}, saveClick = {
saveLanguage()
}
)
Spacer(modifier = Modifier.height(xx.dp))
LazyColumn (
Modifier
.fillMaxWidth()
.weight(1f)
.background(
color = colorResource(id = R.color.xx),
shape = RoundedCornerShape(
topStart = (xx).dp,
topEnd = (xx).dp
)
)
) {
items(languageList) { language ->
ShowLanguageItem(language = language, onLanguageSelected = onLanguageSelected)
Spacer(modifier = Modifier
.fillMaxWidth()
.height((xx).dp)
.padding(start = (xx).dp, end = (xx).dp)
.background(colorResource(id = R.color.xx)))
}
}
}
}
/**
* 展示单个Item view
*/
@Composable
fun ShowLanguageItem(language: Language, onLanguageSelected: (Language) -> Unit) {
Row (
Modifier
.fillMaxWidth()
.height((xx).dp)
.padding(start = (xx).dp, end = (xx).dp)
.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = null
) {
onLanguageSelected(language)
},
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Start
) {
// 文本
Box(modifier = Modifier
.fillMaxHeight()
.weight(1f),
contentAlignment = Alignment.CenterStart
) {
Text(
modifier = Modifier.padding(start = xx.dp, end = xx.dp),
text = show,
style = TextStyle(color = xxx , fontSize = xxx),
maxLines = 1,
overflow = TextOverflow.Ellipsis,
textAlign = TextAlign.Center
)
}
if (language.isSelected) {
Image ( painter = painterResource(id = xxx),
contentDescription = null,
modifier = Modifier.width(xxx).height(xxx).clip(RoundedCornerShape(size = xxx)),
contentScale = ContentScale.Crop)
}
}
}
/**
* 语言选中时,及时去
* 更新语言列表选中状态
*/
private val onLanguageSelected : (Language) -> Unit = { selected ->
checkLanguageID = selected.id
isCheck = checkLanguageID == spLanguageID
languageList = languageList.map { language ->
language.copy(isSelected = language.id == selected.id)
}
}
/**
* 保存语言逻辑
*/
private fun saveLanguage() {
if (isCheck) {
return
}
if (checkLanguageID != AUTO_TAG) {
//保存到Sp中
xxx.saveKeyString(this, "sp存储的key值", checkLanguageID)
}
//切换保存语言
if (checkLanguageID.isNotEmpty()) {
setLocale(languageID = checkLanguageID)
}
//关闭所有的activity,打开MainActivity
备注:此处自己实现
关闭所有的activity 自己实现
打开 MainActivity如下参考,具体自己实现
openActivity(context = this, MainActivity::class.java)
}
/**
* 切换语言函数
*/
private fun setLocale(languageID: String) {
val mutableMap = mutableMapOf(
AUTO_TAG to MainApplication.GlobalDpData.defaultLanguage,
"English" to "en",
"Deutsch" to "de",
"简体中文" to "zh",
)
val languageSet = mutableMap[languageID] ?: MainApplication.GlobalDpData.defaultLanguage
MainApplication.GlobalDpData.language = languageSet
if (languageID == AUTO_TAG) {
// 更新跟随系统语言设置,置为空字符
备注:此处自己实现保存到sp中
} else {
// 不跟随系统设置,更新语言设置
备注:此处自己实现保存到sp中
}
}
总结
以上是语言切换的具体大部分实现,小部分未提供的compose 实现,需要开发者自己补充;主要参考点在语言切换的逻辑。