Establecer dinámicamente el color del tema
Estoy utilizando temas (dinámicamente) en mi aplicación para Android, así:
My_layout.xml (extracto):
- Android: theme = "@ android: style / Theme.NoTitleBar.Fullscreen" No funciona android
- LinearLayout no establece el atributo layout_height requerido
- Error al agregar tema personalizado a la aplicación
- ¿Cómo agregar atributos de varios temas a la misma actividad en el manifiesto de Android?
- Temas de Android ListView
<TextView android:id="@+id/myItem" style="?my_item_style" />
Attrs.xml (extracto):
<attr name="my_item_style" format="reference" />
Themes.xml (extracto):
<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 (extracto):
<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>
Por lo tanto, como puede ver, estoy estableciendo temas dinámicamente. Estoy usando esta clase:
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; } }
}
¿Qué quiero saber, hay una manera de cómo hacer esto (cambiar el color del tema) en el código? Por ejemplo, tengo el siguiente código (extracto):
((TextView) findViewById(R.id.myItem)).setTextColor(R.color.blue);
Se puede hacer por algún método auxiliar, que utilizaría el comando switch
para los temas disponibles y devolverá el color correcto para un tema. Pero me gustaría saber si hay alguna manera mejor, más agradable y más rápida.
¡Gracias!
- ScrollView: Cambia el color del efecto de borde con Holo
- Android: No se puede diseñar el divisor de hilado
- Temas de Android dificultan la implementación de la más simple: personalizado por color de tema
- ¿Puedo configurar los estilos personalizados globales de aplicaciones para los widgets de Android-support-design?
- Icono de aplicación no aparece en Actionbar (Android Studio 1.0.1)
- Utilice el cuadro combinado Tema encima del diseño para elegir un diseño diferente o corrija las referencias de estilos del tema
- El cambio de tema no funciona en <4.0 como debería
- ¿Para usar layout_marginLeft en un estilo de botón aplicado como tema?
Si entiendo corectly usted está buscando una manera de
- Extraer un estilo de un tema,
- Extraer un valor (color de texto) de dicho estilo.
Hagámoslo.
// 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); }
Un par de notas:
-
TypedArray
no admite la obtención de elementos vectoriales de soporte y referencias de temas en listas de estado de color en niveles de API más antiguos. Si está dispuesto a utilizar AppCompat API interna, puede intentarTintTypedArray
. - Asignar
int[]
todo el tiempo es costoso, lo convierten en unstatic final
. - Si desea resolver varios atributos a la vez, la matriz de atributos debe ser ordenada. De lo contrario se bloquea a veces.
<declare-styleable>
genera tal matriz e índices correspondientes para usted.
Finalmente lo he hecho usando el siguiente método:
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()); } }
Esto devuelve el color según mi tema (usé prefijos).
¿Has comprobado esta demostración de MultipleThemeMaterialDesign ?
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); } } }; }
Ver ejemplo completo de demostración.
¿Qué pasa con la identificación del tema a través de Intent
?
Intent intent = new Intent(activity, MyActivity.class); intent.putExtra("theme", R.style.MainTheme_Green); activity.startActivity(intent);
Y luego en onCreate
:
// assuming that MainTheme_Blue is default theme setTheme(getIntent().getIntExtra("theme", R.style.MainTheme_Blue));
Dado el hecho de que cada recurso es un campo dentro de la clase R, puedes buscarlos usando la reflexión. Eso es costoso, pero puesto que usted va a conseguir un valor int, usted puede almacenarlos después de que usted los consiga y evitar la caída del funcionamiento. Y puesto que los métodos que utilizan recursos toman cualquier int, usted puede utilizar una variable del int como placeholder, y después poner el color deseado en él.
Para obtener cualquier recurso:
String awesomeColor = "blue"; int color = getResourceId(R.color, awesomeColor, false); if(blue>0) ((TextView) findViewById(R.id.myItem)).setTextColor(color);
La función:
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; }
Versión de trabajo aquí: https://github.com/fcopardo/AndroidFunctions/blob/master/src/main/java/com/grizzly/functions/TextFunctions.java
Este tratamiento es válido para cualquier recurso de Android. También puede configurar el tema de esta manera en lugar de utilizar variables intermedias:
public static void onActivityCreateSetTheme(Activity activity) { int theme = getResourceId(R.style, activity.getClass().getSimpleName(), false); if(theme > 0) activity.setTheme(theme); }