Android 如何应用特定于主题的样式?

Android 如何应用特定于主题的样式?,android,styles,themes,Android,Styles,Themes,在这里搜索了几个小时并测试了这个和那个之后,我既不能解决我的问题,也不能在这里找到任何适用于我的问题的问题/答案-但可能我只使用了错误的搜索词-所以我感谢在正确方向上的任何提示 基本上,它是关于一个应用程序使用两个主题(黑暗和光明),其中一些文本视图显示状态-状态可以是开或关,为了更好地识别状态,文本的颜色应该反映状态:红色表示关,绿色表示开 当我没有使用任何主题或样式时,我只是使用TextView的.setColor(#ffff0000)作为红色,以此类推 然后我开始使用暗/光主题,以便在不同

在这里搜索了几个小时并测试了这个和那个之后,我既不能解决我的问题,也不能在这里找到任何适用于我的问题的问题/答案-但可能我只使用了错误的搜索词-所以我感谢在正确方向上的任何提示

基本上,它是关于一个应用程序使用两个主题(黑暗和光明),其中一些文本视图显示状态-状态可以是开或关,为了更好地识别状态,文本的颜色应该反映状态:红色表示关,绿色表示开

当我没有使用任何主题或样式时,我只是使用TextView的.setColor(#ffff0000)作为红色,以此类推

然后我开始使用暗/光主题,以便在不同情况下获得更好的可视性-例如,户外白色背景上的黑色文本更容易阅读

因此,我定义了两个主题,覆盖文本外观:

<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>
现在的挑战/问题是-我如何避免switch语句

在layout.xml文件中引用样式时,可以使用?引用以纪念当前主题。。。(代替“@”)

在这种情况下,我需要在运行时设置样式并尊重主题:因此它必须通过代码而不是xml来完成-但是setTextAppearance只接受样式的id,而不是主题通配符+id

这就是我被困的地方。。。是的,我可以围绕这一点包装一个类,并将其保留在代码中的一行,并在这个类中“隐藏”主题检测/切换语句,但另一方面,Android复杂的样式/主题化架构也应该有一个解决方案,不是吗

只要需要helperclass或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>
它总是使用TextRed的最后一个定义-因此根据上面的定义,文本将以黄色显示。当我交换两个TextRed定义的顺序时,它使用的是最后一个定义-#ffff0000-,文本是红色的

因此,在运行时设置样式时,setTextAppearance不支持主题-它不区分当前主题和两个定义的样式

我们可以根据主题定义一种具有不同textcolor值的样式,并且根据所选主题,它的颜色正确-只要在layout.xml中指定了它的样式,或者主题集的此样式为默认样式

但是,当在运行时在代码中动态切换样式时,我们仍然需要类似上面的switch语句的内容—检测选择了哪个主题,并根据主题将不同的样式应用于textview

我想要实现的是,它应该根据当前主题选择正确的“TextRed”样式。所以不需要硬编码主题意识。。。一旦添加了一个新主题,所提到的switch语句也必须更新

编辑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>

...
...
#ffffffff
#ff000000
layout.xml中的引用是:

<TextView style="@style/TextNormal" .../>

回答我自己的问题:

因此,除了我的-working-switchstatement之外,还需要一些代码,但至少没有主题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

汤姆·亚什——谢谢你的回答!带着一些希望,我尝试了你的想法,但它并没有解决问题-为了更好的可读性,我编辑/添加了上述问题的结果。只要样式分配是静态的(通过layout.xml),您的方法是好的,并且可以正常工作(像我的方法一样),但是在更改每个代码的样式时,它失败了(像我的方法一样):(
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>
<TextView style="@style/TextNormal" .../>
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