Bil*_*ote 8 string resources customization android themes
假设我有2个主题的应用程序:男性化和女性化.主题只是改变了调色板和一些drawables,以吸引用户的首选品味.
非常感谢http://www.androidengineer.com/2010/06/using-themes-in-android-applications.html提供了他的工作提示.
但现在让我们说我希望得到一个有点可爱的应用程序,不仅改变颜色和drawables,但我也想改变字符串.例如,我可能想要添加一个盗版主题,然后"提交"将是"Arrrrgh!"
所以,我的基本问题是:如何通过用户可选择的主题更改我的应用程序中的字符串?
编辑:
做到这一点:该应用程序有12个按钮和32个文本视图我想要主题依赖,我想在没有巨型映射或大量定制attrs的情况下完成此操作.
所有3种当前解决方案都可以使用.寻找更干净的东西虽然我不知道这样的野兽存在.
是的,它可以完成,这是如何:首先你必须定义一个主题属性,如下所示:
<attr name="myStringAttr" format="string|reference" />
Run Code Online (Sandbox Code Playgroud)
然后,在您的主题中添加此行
<item name="myStringAttr">Yarrrrr!</item>
Run Code Online (Sandbox Code Playgroud)
要么
<item name="myStringAttr">@string/yarrrrr</item>
Run Code Online (Sandbox Code Playgroud)
然后,您可以在XML文件中使用此属性(请注意?而不是@).
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="?attr/myStringAttr" />
Run Code Online (Sandbox Code Playgroud)
或者,从代码中,如下:
public CharSequence resolveMyStringAttr(Context context)
{
Theme theme = context.getTheme();
TypedValue value = new TypedValue();
if (!theme.resolveAttribute(R.attr.myStringAttr, value, true)) {
return null;
}
return value.string;
}
Run Code Online (Sandbox Code Playgroud)
假设我有一个有 2 个主题的应用程序:男性和女性。这些主题只是简单地改变了调色板和一些可绘制的东西来吸引用户的喜好。
我们假装你在做别的事怎么样?这是一种设计反模式,根据性别关联特定颜色(例如,“女孩喜欢粉色”)。
这并不是说你的技术目标不好,只是说这是一个非常典型的例子。
例如,我可能想添加一个海盗主题,然后“提交”将是“Arrrrgh!”
仅当“取消”映射到“Avast!”时。
如何通过用户可选择的主题更改整个应用程序中的字符串?
你还没有说这些字符串是从哪里来的。它们是字符串资源吗?数据库条目?您从 Web 服务中检索的内容?还有别的事吗?
我暂时假设这些是字符串资源。根据定义,您需要拥有 N 个字符串副本,每个主题一个。
由于性别和盗版状态不是 Android 跟踪的可能的资源集限定符,因此您不能让这些字符串资源位于不同的资源集中。虽然它们可能位于不同的文件中(例如,res/values/strings_theme1.xml),但文件名不是字符串资源标识符的一部分。因此,您最终将不得不使用某种前缀/后缀来跟踪哪些字符串属于哪些主题(例如,@string/btn_submit_theme1)。
如果这些字符串在运行时没有改变——它只是布局资源中的任何内容——您可以从Chris Jenkins 的 Calligraphy 库中获取一页。他有自己的 子类LayoutInflater,用于重载一些标准 XML 属性。就他而言,他的重点是android:fontFamily,他支持映射到资源中的字体文件。
在你的情况下,你可能会超载android:text。在您的布局文件中,您可以将其作为所需字符串资源的基本名称,而不是指向任何实际字符串,而无需任何主题标识符(例如,如果真正的字符串是@string/btn_submit_theme1和 kin,您可以拥有android:text="btn_submit")。您的LayoutInflater子类将获取该值,附加主题名称后缀,用于getIdentifier()查找Resources实际的字符串资源 ID,然后从那里获取与您的主题相关的字符串。
对此的一种变体是将基本名称放入android:tag而不是android:text. android:text可能指向您真正的字符串资源之一,以帮助进行 GUI 设计等。您LayoutInflater将获取该标签并使用它在运行时派生正确的字符串。
如果您要将文本替换为从基于主题的字符串资源中提取的其他文本,您可以将获取字符串给定的基本名称逻辑隔离到您可以应用的静态实用程序方法中。
虽然一开始要做到这一点需要一些工作,但就受影响的 UI 小部件和字符串的数量而言,它将扩展到任意复杂性。您仍然必须记住为您定义的任何新字符串添加所有主题的值(创建自定义 Lint 检查或 Gradle 任务来验证这一点的奖励点)。