在这里搜索了几个小时并测试了这个和那个之后,我既无法解决我的问题,也无法在这里找到适用于我的问题的任何问题/答案 - 但也许我只使用了错误的搜索词 - 所以我感谢任何正确方向的提示!
基本上,它是关于使用2个主题(深色和浅色(的应用程序,其中某些TextView显示状态 - 状态可以是"打开"或"关闭",为了更好地识别状态,文本的颜色应反映状态:红色表示关闭,绿色表示打开。
当我不使用任何主题或样式时,我只是使用 TextView 的 .setColor(#ffff0000( 作为红色,依此类推......
然后我开始使用深色/浅色主题在不同情况下获得更好的可见性 - 例如,白色背景上的户外黑色文本更容易阅读。
因此,我定义了我的 2 个主题,覆盖文本外观:
<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 样式,并添加一个要在浅色主题中使用的样式,为了测试,我只是做了一个奇怪的颜色看看它是否有效:
<style name="TextRedLight">
<item name="android:textColor">#ffffff00</item>
</style>
如果我在 TextView 的 .setTextAppearance 周围放置一个开关语句,并根据所选主题选择正确的样式 - 伪代码,这也有效:
switch (currentheme) {
case Dark: tv.setTextAppearance(... R.style.TextRed); break;
case Light: tv.setTextAppearance(... R.style.TextRedLight); break;
}
现在的挑战/问题是 - 如何避免 switch 语句?
当引用布局.xml文件中的样式时,我们可以使用 ? 引用来遵循当前主题...(而不是"@"(
在这种情况下,我需要在运行时设置样式并遵循主题:所以它必须通过代码而不是 xml 来完成 - 但 setTextAppearance 只接受样式的 id,而不是主题通配符 + id...
而这个我被困住了...是的,我可以围绕它包装一个类并将其保留在代码中的一行中,并在此类中"隐藏"主题检测/切换语句,但另一方面 - Android 的复杂样式/主题架构也应该有解决这个问题的方法,不是吗......?
使用主题和样式似乎有点毫无意义,只要需要帮助程序类或 switch/if 语句来完成一些增强的东西......
感谢您的任何提示/想法!!
编辑 1 - 在托马斯回答之后:更新的样式.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>
在布局.xml中分配了 TextNormal 的文本视图,或者在从两个主题引用 TextNormal 时,使用:
<item name="android:textAppearance">@style/TextNormal</item>
像以前一样工作(使用这种不同的方法(,使用红色文本时也是如此。
但最初的问题仍然存在:当我想(在运行时(将文本的颜色更改为红色时,使用
tv.setTextAppearance(getActivity(),R.style.TextRed)
它始终使用 TextRed 的最后一个定义 - 因此使用上述定义,文本将 #ffffff00 -> 着色为黄色。 当我交换 2 个 TextRed 定义的顺序时,它使用的是最后一个定义 - #ffff0000 - 并且文本是红色的。
因此,在运行时设置样式时,setTextAppearance 不是主题感知的 - 它不区分当前主题和 2 种定义的样式。
我们可以根据主题定义一种具有不同文本颜色值的样式,并且根据所选主题,它的颜色正确 - 只要它的样式在布局中分配.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);
工作,但很复杂,如果这就是它本来的样子,那就太可悲了...... ;)
你试过这个吗?
<style name="Theme.MyApp" parent="Theme.Sherlock">
...
</style>
<style name="Theme.MyApp.Light" parent="Theme.Sherlock.Light">
...
</style>
<style name="TextNormal" parent="Theme.MyApp">
<item name="android:textColor">#ffffffff</item>
</style>
<style name="TextNormal" parent="Theme.MyApp.Light">
<item name="android:textColor">#ff000000</item>
</style>
布局中的引用.xml为:
<TextView style="@style/TextNormal" .../>
回答我自己的问题:
找到这个
所以不是我的 - 工作 - switch语句,仍然需要一些代码,但它至少没有主题 ID 的硬编码,... ->用这个片段更新了我的 getThemedStyle
public static int getThemedStyle(int normalStyle) {
Resources.Theme theme = appContext.getTheme();
TypedValue styleID = new TypedValue();
if (theme.resolveAttribute(R.attr.TextAppRed, styleID, true)) return styleID.data;
else return normalStyle;
} //getThemedStyle