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



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

基本上,它是关于使用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

相关内容

  • 没有找到相关文章

最新更新