动态设置主题颜色

时间:2017-03-21 09:06:49

标签: android android-activity colors themes

我在我的Android应用中使用主题(动态),如下所示:

my_layout.xml (摘录):

<TextView
    android:id="@+id/myItem"
    style="?my_item_style" />

attrs.xml (摘录):

<attr name="my_item_style" format="reference" />

themes.xml (摘录):

<style name="MainTheme.Blue">
      <item name="my_item_style">@style/my_item_style_blue</item>
</style>

<style name="MainTheme.Green">
      <item name="my_item_style">@style/my_item_style_green<item>
</style>

styles.xml (摘录):

<style name="my_item_style_blue">
      <item name="android:textColor">@color/my_blue</item>
</style>

<style name="my_item_style_green">
      <item name="android:textColor">@color/my_blue</item>
</style>

因此,正如您所看到的,我正在动态设置主题。我正在使用这个课程:

public class ThemeUtils {

  private static int sTheme;
  public final static int THEME_BLUE = 1;
  public final static int THEME_GREEN = 2;

  public static void changeToTheme(MainActivity activity, int theme) {
      sTheme = theme;
      activity.startActivity(new Intent(activity, MyActivity.class));
  }

  public static void onActivityCreateSetTheme(Activity activity)
  {
      switch (sTheme)
      {
          default:
          case THEME_DEFAULT:
          case THEME_BLUE:
              activity.setTheme(R.style.MainTheme_Blue);
              break;
          case THEME_GREEN:
              activity.setTheme(R.style.MainTheme_Green);
              break;
      }
  }

}

我想知道的是,有没有办法在代码中执行此操作(更改主题颜色)?例如,我有以下代码(提取):

((TextView) findViewById(R.id.myItem)).setTextColor(R.color.blue);

可以通过一些辅助方法来完成,该方法将switch命令用于可用主题并返回主题的正确颜色。但我想知道是否有更好,更好,更快的方式。

谢谢!

5 个答案:

答案 0 :(得分:4)

我终于使用以下方法完成了它:

public static int getColor(String colorName) {
    Context ctx = getContext();
    switch (sTheme) {
        default:
        case THEME_DEFAULT:
            return ctx.getResources().getIdentifier("BLUE_" + colorName, "color", ctx.getPackageName());
        case THEME_BLUE:
            return ctx.getResources().getIdentifier("BLUE_" + colorName, "color", ctx.getPackageName());
        case THEME_GREEN:
            return ctx.getResources().getIdentifier("GREEN_" + colorName, "color", ctx.getPackageName());
    }
}

根据我的主题返回颜色(我使用了前缀)。

答案 1 :(得分:3)

如果我理解你正在寻找一种方法

  1. 从主题中提取样式
  2. 从所述样式中提取值(文本颜色)。
  3. 让我们来看看。

    // Extract ?my_item_style from a context/activity.
    final TypedArray a = context.obtainStyledAttributes(new int[] { R.attr.my_item_style });
    @StyleRes final int styleResId = a.getResourceId(0, 0);
    a.recycle();
    
    // Extract values from ?my_item_style.
    final TypedArray b = context.obtainStyledAttributes(styleResId, new int[] { android.R.attr.textColor });
    final ColorStateList textColors = b.getColorStateList(0);
    b.recycle();
    
    // Apply extracted values.
    if (textColors != null) {
        textView.setTextColor(textColors);
    }
    

    几点说明:

    1. TypedArray不支持在旧API级别的颜色状态列表中获取支持向量drawable和主题引用。如果您愿意使用AppCompat内部API,则可能需要尝试TintTypedArray
    2. 始终分配int[]代价高昂,请将其设为static final
    3. 如果要一次解析多个属性,必须对属性数组进行排序!否则它有时会崩溃。 <declare-styleable>为您生成此类数组和相应的索引。

答案 2 :(得分:1)

您是否已查看此MultipleThemeMaterialDesign演示?

enter image description here

<强> SettingActivity:

let pdfURL = URL(fileURLWithPath: inputfile) // returns a non-optional URL
let pdfDoc = PDFDocument(url: pdfURL)

查看演示的完整示例。

答案 3 :(得分:0)

如何通过Intent传递主题ID?

Intent intent = new Intent(activity, MyActivity.class);
intent.putExtra("theme", R.style.MainTheme_Green);
activity.startActivity(intent);

然后在onCreate

// assuming that MainTheme_Blue is default theme
setTheme(getIntent().getIntExtra("theme", R.style.MainTheme_Blue));

答案 4 :(得分:0)

鉴于每个资源都是R类的字段,您可以使用反射查找它们。这是非常昂贵的,但由于您将获得一个int值,您可以在获得它们之后存储它们并避免性能下降。并且由于使用资源的方法采用任何int,您可以使用int变量作为占位符,然后将所需的颜色放入其中。

获取任何资源:

String awesomeColor = "blue";
int color = getResourceId(R.color, awesomeColor, false);
if(blue>0) ((TextView) findViewById(R.id.myItem)).setTextColor(color);

功能:

public static int getResourceId(Class rClass, String resourceText, boolean showExceptions){

        String key = rClass.getName()+"-"+resourceText;

        if(FailedResourceMap.containsKey(key)) return 0;
        if(ResourceMap.containsKey(key)) return ResourceMap.get(rClass.getName()+"-"+resourceText);

        try {

            String originalText = resourceText;
            if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.GINGERBREAD){
                resourceText = ValidationFunctions.normalizeText(resourceText);
            }
            resourceText = resourceText.replace("?", "").replace("  ", " ").replace(" ", "_").replace("(", "").replace(")", "");

            int resource = rClass.getDeclaredField(resourceText).getInt(null);
            ResourceMap.put(rClass.getName()+"-"+originalText, resource);

            return resource;
        } catch (IllegalAccessException | NullPointerException e) {
            FailedResourceMap.put(key, 0);
            if(showExceptions) e.printStackTrace();
        } catch (NoSuchFieldException e) {
            FailedResourceMap.put(key, 0);
            if(showExceptions) e.printStackTrace();
        }

        return 0;
    }

此处的工作版本:https://github.com/fcopardo/AndroidFunctions/blob/master/src/main/java/com/grizzly/functions/TextFunctions.java

此处理对任何Android资源都有效。您也可以这样设置主题,而不是使用中间变量:

public static void onActivityCreateSetTheme(Activity activity)
  {
    int theme = getResourceId(R.style, activity.getClass().getSimpleName(), false);
    if(theme > 0) activity.setTheme(theme);
  }