【发布时间】:2012-05-28 06:03:50
【问题描述】:
在这里搜索了几个小时并测试了这个和那个之后,我既不能解决我的问题,也不能在这里找到任何适用于我的问题的问题/答案 - 但也许我只使用了错误的搜索词 - 所以我很感激对于正确方向的任何提示!
基本上它是关于使用 2 个主题(深色和浅色)的应用程序,其中一些 TextView 显示状态 - 状态可以是打开或关闭,为了更好地识别状态,文本的颜色应该反映状态:红色为关闭,绿色为开启。
当我没有使用任何主题或样式时,我只是将 TextView 的 .setColor(#ffff0000) 用于红色,等等......
然后我开始使用深色/浅色主题在不同情况下获得更好的可见性 - 例如。户外白色背景上的黑色文本更易于阅读。
因此我定义了我的 2 个主题,覆盖了 textAppearance:
<style name="Theme.MyApp" parent="Theme.Sherlock">
...
<item name="android:textAppearance">@style/TextNormal</item>
...
</style>
<style name="Theme.MyApp.Light" parent="Theme.Sherlock.Light">
...
<item name="android:textAppearance">@style/TextNormalLight</item>
...
<style name="TextNormal">
<item name="android:textColor">#ffffffff</item>
</style>
<style name="TextNormalLight">
<item name="android:textColor">#ff000000</item>
</style>
这很好用,“正常”文本视图会根据主题以正确的颜色显示。到目前为止一切顺利!
我没有使用 TextView 的 setColor,而是改用 .setTextAppearance tv.setTextAppearance(getSherlockActivity(), R.style.TextRed);
并定义了一些样式(只粘贴一个,其他是TextGreen,...):
<style name="TextRed">
<item name="android:textColor">#ffff0000</item>
</style>
这也很好用!
终于解决了我的问题:
现在我想根据主题为“红色”设置不同的颜色...
所以我保留了 TextRed 样式,并添加了一个在 Light 主题中使用的样式,为了测试,我只是做了一个奇怪的颜色来看看它是否有效:
<style name="TextRedLight">
<item name="android:textColor">#ffffff00</item>
</style>
如果我在 TextView 的 .setTextAppearance 周围放置一个 switch 语句,并根据所选主题选择正确的样式 - 伪代码,这也有效:
switch (currentheme) {
case Dark: tv.setTextAppearance(... R.style.TextRed); break;
case Light: tv.setTextAppearance(... R.style.TextRedLight); break;
}
现在的挑战/问题是 - 我怎样才能避免 switch 语句?
在 layout.xml 文件中引用样式时,我们可以使用 ?引用当前主题...(而不是“@”)
在这种情况下,我需要在运行时设置样式并且尊重主题:所以它必须通过代码而不是 xml 来完成 - 但是 setTextAppearance 只接受一个 id样式,而不是主题通配符 + id...
这是我卡住的地方...是的,我可以围绕这个包装一个类并将其保留在代码中的一行并“隐藏”该类中的主题检测/切换语句,但另一方面手 - Android 复杂的样式/主题架构也应该有解决这个问题的方法,不是吗...?
只要需要帮助类或 switch/if 语句来完成一些增强的事情,使用主题和样式似乎有点无意义......
感谢任何提示/想法!!!
编辑 1 - 在 Tomáš 回答之后: 更新了 style.xml:
<style name="TextNormal" parent="Theme.ARMoDroid">
<item name="android:textColor">#ffffffff</item>
</style>
<style name="TextNormal" parent="Theme.ARMoDroid.Light">
<item name="android:textColor">#ff000000</item>
</style>
<style name="TextRed" parent="Theme.ARMoDroid">
<item name="android:textColor">#ffff0000</item>
</style>
<style name="TextRed" parent="Theme.ARMoDroid.Light">
<item name="android:textColor">#ffffff00</item>
</style>
在 layout.xml 中分配了 TextNormal 的 TextView,或者当从两个主题中引用 TextNormal 时:
<item name="android:textAppearance">@style/TextNormal</item>
像以前一样工作(使用这种不同的方法),在使用红色文本时也是如此。
但最初的问题仍然存在: 当我想(在运行时)将文本的颜色更改为红色时,使用
tv.setTextAppearance(getActivity(),R.style.TextRed)
它总是使用 TextRed 的最后一个定义 - 因此使用上面的定义,文本将被着色为 #ffffff00 -> 黄色。当我交换 2 个 TextRed 定义的顺序时,它使用最后一个定义 - #ffff0000 - 并且文本是红色的。
所以在运行时设置样式时,setTextAppearance 不支持主题 - 它不区分当前主题和 2 个定义的样式。
我们可以根据主题定义一种具有不同文本颜色值的样式,并根据所选主题正确着色 - 只要它的样式在 layout.xml 中指定,或者主题集的默认样式为此样式.
但是在运行时在代码中动态切换样式时,我们仍然需要类似上面的 switch 语句 - 检测选择了哪个主题,并根据主题,将不同的样式应用于 textview。
我想要实现的是,它应该根据当前主题选择正确的“TextRed”样式。所以不需要对主题意识进行硬编码...一旦添加了新主题,上述开关语句也必须更新...
编辑 2:我目前的“解决方案”
我想我也可以发布当前的解决方案,但这并不是一个很好的解决方案 - 尽管它正在工作 - 但它是每种样式的自定义代码,并且对于另一个主题,它甚至是更多代码......
辅助函数如下所示:
public static int getThemedStyle(int normalStyle) {
if (prefs==null) { prefs = PreferenceManager.getDefaultSharedPreferences(appContext); }
int theme = Integer.valueOf(prefs.getString("GUI_Theme","0"));
if (theme==0) return normalStyle; //dark theme
else { //return correct Light-Theme Style
switch (normalStyle) {
case R.style.TextNormal: return R.style.TextNormalLight;
case R.style.TextRed: return R.style.TextRedLight;
case R.style.TextOrange: return R.style.TextOrangeLight;
case R.style.TextGreen: return R.style.TextGreenLight;
case R.style.TextYellow: return R.style.TextYellowLight;
case R.style.TextBlue: return R.style.TextBlueLight;
default: return normalStyle;
} //switch
} //else theme==0
} //getThemedStyle
在片段中,我通过在 onCreate 上调用上述函数来缓存样式引用:
styleRed = preferences.getThemedStyle(R.style.TextRed);
styleOrange = preferences.getThemedStyle(R.style.TextOrange);
styleGreen = preferences.getThemedStyle(R.style.TextGreen);
最后分配样式使用:
tv.setTextAppearance(getSherlockActivity(), styleRed);
工作,但很复杂,如果这就是它原本的样子,那就太可悲了... ;)
【问题讨论】: