2017-03-21 83 views
8

我使用的主题(动态)在我的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命令,并返回正确的颜色为主题进行。但我想知道是否有更好,更好,更快的方法。

谢谢!

+1

从哪里可以设置动态主题?你能分享那些代码吗? – azizbekian

+0

@azizbekian我已经添加了ThemeUtils类,但我不认为它与我的问题有关。 – Tom11

回答

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()); 
    } 
} 

这根据我的主题(我的前缀)返回颜色。

3

如果我理解corectly你正在寻找一种方式来

  1. 提取物从一个主题风格,
  2. 提取的值(文本颜色)说风格。

让我们开始吧。

// 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级别。如果您愿意使用AppCompat内部API,则可以尝试TintTypedArray
  2. 一直分配int[]昂贵,使其成为static final
  3. 如果要一次解析多个属性,必须对属性数组进行排序!否则有时会崩溃。 <declare-styleable>为您生成这样的数组和相应的索引。
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)); 
1

你有没有检查这个MultipleThemeMaterialDesign演示?

enter image description here

SettingActivity:

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    Preferences.applyTheme(this); 
    getDelegate().installViewFactory(); 
    getDelegate().onCreate(savedInstanceState); 
    super.onCreate(savedInstanceState); 
    setToolbar(); 
    addPreferencesFromResource(R.xml.preferences); 
    Preferences.sync(getPreferenceManager()); 
    mListener = new SharedPreferences.OnSharedPreferenceChangeListener() { 
     @Override 
     public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { 
      Preferences.sync(getPreferenceManager(), key); 
      if (key.equals(getString(R.string.pref_theme))) { 
       finish(); 
       final Intent intent = IntentCompat.makeMainActivity(new ComponentName(
         SettingsActivity.this, MainActivity.class)); 
       intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | IntentCompat.FLAG_ACTIVITY_CLEAR_TASK); 
       startActivity(intent); 
      } 
     } 
    }; 
} 

见演示完整的例子。

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); 
    }