android - 在android资源中定义具有不同内容但结构相同的字符串包
问题描述
我有一个游戏,我有一个层次结构,一个赛季有多个级别,一个级别有多个任务。
现在,我有一个活动,它为层次结构的每个部分显示一条祝贺消息,这些部分分为不同的字符串。他们每个人都有:
- 感叹
- 标题
- 描述
- 继续留言
例如季节:
- “欢呼!”
- “赛季结束”
- “你已成功完成第 X 季”
- “继续第 X+1 季”
我的第一个想法是创建一个包含适当值的枚举。像这样:
enum class CongratulationsType(val exclamation: String, val header: String) {
SEASON("HURRAY!", "You finished season %d!!"),
LEVEL("YAY!", "Well done! Level over!"),
TASK("NICE!", "This looked too easy")
}
...
val headerString = CongratulationsType.SEASON.header
但是字符串应该保存在资源中。所以我必须将字符串放入资源中并将资源正确链接到枚举值。
这意味着我有点做这项工作两次。我会在没有“绑定结构”的资源文件中定义字符串,然后将它们放入枚举中以具有“绑定结构”。“绑定结构”是指上面描述的结构,特定字段必须存在,并且我可以调用类似CongratulationsType.SEASON.header
.
我的问题是:是否可以在某个定义的结构中“打包”字符串并使该结构类似于枚举或哈希图?就像是:
包定义
<resources>
<pack_def name="congrats">
<string name="exclamation"/>
<string name="header"/>
...
</pack_def>
<resources>
包实现
<resources>
<pack name="season" type="congrats">
<string name="exclamation">HURRAY!</string>
<string name="header">Season Finished</string>
...
</pack>
<resources>
用法
// In code
//// function definition
fun setMessage(congrats: Congrats) {
exclamationTextView.text = congratsType.exclamation
headerTextView.text = congratsType.header
...
}
//// function use
setMessage(Congrats.Season)
// In Resources
<TextView
android:text="@packs/congrats/season/exclamation"
/>
我知道我可以使用字符串数组资源,但它们看起来有点“不干净”,因为正如我所说,我希望结构是“绑定的”并像枚举一样调用。我特别要求一种方法尽可能接近枚举,而不必为每个枚举值的每个字段分配资源。
解决方案
我的问题是:是否可以将字符串“打包”在某个已定义的结构中,并使该结构类似于枚举或哈希图?就像是:
android:text="@packs/congrats/season/exclamation"
简短的回答 - 不。Android 将不知道如何从这些新结构中解析和提取值。
你可以做什么:
- 创建4个字符串资源数组:Exclamations、Headers、Descriptions、Continue Messages;
- 使用 4 个字符串变量创建 kotlin 数据类。让我们称之为
Congratulation
; - 将资源映射到具有
Congratulation
s 的数组。
例子:
在 strings.xml 文件中声明下一个数组:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="exclamations">
<item>Exclamation 1!!!</item>
<item>Exclamation 2!!!</item>
...
<item>Exclamation N!!!</item>
</string-array>
<string-array name="headers">
<item>Header 1</item>
<item>Header 2</item>
...
<item>Header N</item>
</string-array>
<!-- etc. -->
</resources>
或者您可以使用这些数组中已经定义的资源来对它们进行排序:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="exclamations">
<item>@string/exclamation_1</item>
<item>@string/exclamation_2</item>
...
<item>@string/exclamation_n</item>
</string-array>
<!-- etc. -->
</resources>
定义数据类:
data class Congratulation(val exclamation: String, val header: String,
val description: String, val continueMessage: String)
地图资源:
val exclamations = context.resources.getStringArray(R.array.exclamations)
val headers = context.resources.getStringArray(R.array.headers)
val descriptions = context.resources.getStringArray(R.array.descriptions)
val continueMessages = context.resources.getStringArray(R.array.continue_messages)
val congratulations = exclamations.mapIndexed { i, exclamation ->
Congratulation(exclamation, headers[i], descriptions[i], continueMessages[i])
}
优点
- 代码中无需提及每个字符串资源,只有4个数组资源;
- 按照第一点,每次添加新值时都不需要修改代码。您可以在应用程序启动时初始化此数组一次并稍后使用。
缺点
- 翻译顺序必须准确!如果您不小心更改了订单
<string-array>
- 不会出现警告。您必须手动检查订单或创建特定测试; - 如果您不小心将较少的条目添加到任何
headers
,descriptions
或continueMessages
数组 - 应用程序将与IndexOutOfBoundsException
. 虽然,一旦您尝试映射值,它就会崩溃并且很容易调试。 - 使用
when
语句变得不可能。
推荐阅读
- python - 更改 seaborn pairplot 对角线颜色
- scala - Scala 是否可以异步运行循环?
- java - java中斐波那契堆consolidate方法的实现,IndexofBoundsException的错误
- asp.net - 如何在aspx页面中获取请求值
- c - scanf() 的 char 函数采用 \n 输入而不是 char?
- node.js - 持久化 NodeJS 套接字
- python - Python 中的 Selenium 代码会产生语法错误
- javascript - 如何使用jQuery删除空格字符后的文本?
- php - MySql 8.0 读取速度
- apache-superset - 如何在 Superset 的 FlaskAppBuilder 中同时支持 OAuth 和 Basic Auth