¿Cómo _realmente_ cambia programáticamente el color primario y de acento en Android Lollipop?

En primer lugar, esta pregunta plantea una pregunta muy similar. Sin embargo, mi pregunta tiene una diferencia sutil.

Lo que me gustaría saber es si es posible cambiar programáticamente el atributo colorPrimary de un tema por un color arbitrario .

Entonces, por ejemplo, tenemos:

  #ff0000 #ff0000  

En tiempo de ejecución, el usuario decide que quiere usar #ccffff como color primario. Por supuesto, no hay forma de que pueda crear temas para todos los colores posibles.

No me importa si tengo que hacer hacky cosas, como confiar en las partes internas privadas de Android, siempre y cuando funcione con el SDK público.

Mi objective es eventualmente tener el ActionBar y todos los widgets como un CheckBox para usar este color primario.

Los temas son inmutables, no puedes.

Leí los comentarios sobre la aplicación de contactos y cómo usa un tema para cada contacto.

Probablemente, la aplicación de contactos tiene algunos temas predefinidos (para cada color principal de material desde aquí: http://www.google.com/design/spec/style/color.html ).

Puede aplicar un tema antes del método setContentView en el método onCreate.

Luego, la aplicación de contactos puede aplicar un tema al azar a cada usuario.

Este método es:

 setTheme(R.style.MyRandomTheme); 

Pero este método tiene un problema, por ejemplo, puede cambiar el color de la barra de herramientas, el color del efecto de desplazamiento, el color de ondulación, etc., pero no puede cambiar el color de la barra de estado y el color de la barra de navegación (si quiere cambiarlo también).

Luego, para resolver este problema, puede usar el método antes y:

 if (Build.VERSION.SDK_INT >= 21) { getWindow().setNavigationBarColor(getResources().getColor(R.color.md_red_500)); getWindow().setStatusBarColor(getResources().getColor(R.color.md_red_700)); } 

Estos dos métodos cambian la navegación y el color de la barra de estado. Recuerde, si configura su barra de navegación translúcida, no puede cambiar su color.

Este debería ser el código final:

 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setTheme(R.style.MyRandomTheme); if (Build.VERSION.SDK_INT >= 21) { getWindow().setNavigationBarColor(getResources().getColor(R.color.myrandomcolor1)); getWindow().setStatusBarColor(getResources().getColor(R.color.myrandomcolor2)); } setContentView(R.layout.activity_main); } 

Puede usar un interruptor y generar un número aleatorio para usar temas aleatorios, o, como en la aplicación de contactos, cada contacto probablemente tenga asociado un número predefinido.

Una muestra de tema:

  

Lo siento por mi ingles.

Puede usar Theme.applyStyle para modificar su tema en tiempo de ejecución al aplicarle otro estilo.

Digamos que tienes estas definiciones de estilo:

     

Ahora puedes parchar tu tema en el tiempo de ejecución así:

 getTheme().applyStyle(R.style.OverlayPrimaryColorGreen, true); 

¡El método applyStyle debe applyStyle antes de que el diseño se infle! A menos que cargue la vista manualmente, debe aplicar estilos al tema antes de llamar a setContentView en su actividad.

Por supuesto, esto no se puede usar para especificar un color arbitrario, es decir, uno de cada 16 millones (256 3 ) colores. Pero si escribe un pequeño progtwig que genere las definiciones de estilo y el código de Java para usted, entonces algo como uno de 512 (8 3 ) debería ser posible.

Lo que hace que esto sea interesante es que puedes usar diferentes superposiciones de estilo para diferentes aspectos de tu tema. Simplemente agregue algunas definiciones de superposición para colorAccent por ejemplo. Ahora puede combinar diferentes valores para color primario y color de acento casi arbitrariamente.

He creado alguna solución para hacer temas de cualquier color, tal vez esto puede ser útil para alguien. API 9+

1. primero crea ” res / values-v9 / ” y coloca allí este archivo: styles.xml y la carpeta regular “res / values” se usará con tus estilos.

2. Pon este código en tu res / values ​​/ styles.xml:

      

3. en AndroidManifest:

  

4. crea una nueva clase con el nombre “ThemeColors.java”

 public class ThemeColors { private static final String NAME = "ThemeColors", KEY = "color"; @ColorInt public int color; public ThemeColors(Context context) { SharedPreferences sharedPreferences = context.getSharedPreferences(NAME, Context.MODE_PRIVATE); String stringColor = sharedPreferences.getString(KEY, "004bff"); color = Color.parseColor("#" + stringColor); if (isLightActionBar()) context.setTheme(R.style.AppTheme); context.setTheme(context.getResources().getIdentifier("T_" + stringColor, "style", context.getPackageName())); } public static void setNewThemeColor(Activity activity, int red, int green, int blue) { int colorStep = 15; red = Math.round(red / colorStep) * colorStep; green = Math.round(green / colorStep) * colorStep; blue = Math.round(blue / colorStep) * colorStep; String stringColor = Integer.toHexString(Color.rgb(red, green, blue)).substring(2); SharedPreferences.Editor editor = activity.getSharedPreferences(NAME, Context.MODE_PRIVATE).edit(); editor.putString(KEY, stringColor); editor.apply(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) activity.recreate(); else { Intent i = activity.getPackageManager().getLaunchIntentForPackage(activity.getPackageName()); i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); activity.startActivity(i); } } private boolean isLightActionBar() {// Checking if title text color will be black int rgb = (Color.red(color) + Color.green(color) + Color.blue(color)) / 3; return rgb > 210; } } 

5. y antes de llamar a setContentView (R.layout.activity_main) , solo agregue:

 new ThemeColors(this); 

para cambiar el color, reemplace Aleatorio con su RGB:

  findViewById(R.id.button).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int red= new Random().nextInt(255); int green= new Random().nextInt(255); int blue= new Random().nextInt(255); ThemeColors.setNewThemeColor(MainActivity.this, red, green, blue); } }); 

enter image description here

La biblioteca GreenMatter puede ayudarlo a lograr la funcionalidad que está buscando:

https://github.com/negusoft/GreenMatter

Usé el código de Dahnark, pero también necesito cambiar el fondo de ToolBar:

 if (dark_ui) { this.setTheme(R.style.Theme_Dark); if (Build.VERSION.SDK_INT >= 21) { getWindow().setNavigationBarColor(getResources().getColor(R.color.Theme_Dark_primary)); getWindow().setStatusBarColor(getResources().getColor(R.color.Theme_Dark_primary_dark)); } } else { this.setTheme(R.style.Theme_Light); } setContentView(R.layout.activity_main); toolbar = (Toolbar) findViewById(R.id.app_bar); if(dark_ui) { toolbar.setBackgroundColor(getResources().getColor(R.color.Theme_Dark_primary)); } 

Puede que esto no sea exactamente lo que quieres, pero esta respuesta funciona para mí.

Me gustaría ver el método también, donde estableces una vez para todas tus actividades. Pero hasta donde sé, debes establecer cada actividad antes de mostrar cualquier punto de vista.

Para referencia, verifique esto:

http://www.anddev.org/applying_a_theme_to_your_application-t817.html

Editar (copiado de ese foro):

 protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Call setTheme before creation of any(!) View. setTheme(android.R.style.Theme_Dark); // ... setContentView(R.layout.main); } 

UTILICE UNA BARRA DE HERRAMIENTAS

Puede establecer dinámicamente un color de elemento de barra de herramientas personalizado creando una clase de barra de herramientas personalizada:

 package view; import android.app.Activity; import android.content.Context; import android.graphics.ColorFilter; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.support.v7.internal.view.menu.ActionMenuItemView; import android.support.v7.widget.ActionMenuView; import android.support.v7.widget.Toolbar; import android.util.AttributeSet; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.widget.AutoCompleteTextView; import android.widget.EditText; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.TextView; public class CustomToolbar extends Toolbar{ public CustomToolbar(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); // TODO Auto-generated constructor stub } public CustomToolbar(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub } public CustomToolbar(Context context) { super(context); // TODO Auto-generated constructor stub ctxt = context; } int itemColor; Context ctxt; @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { Log.d("LL", "onLayout"); super.onLayout(changed, l, t, r, b); colorizeToolbar(this, itemColor, (Activity) ctxt); } public void setItemColor(int color){ itemColor = color; colorizeToolbar(this, itemColor, (Activity) ctxt); } /** * Use this method to colorize toolbar icons to the desired target color * @param toolbarView toolbar view being colored * @param toolbarIconsColor the target color of toolbar icons * @param activity reference to activity needed to register observers */ public static void colorizeToolbar(Toolbar toolbarView, int toolbarIconsColor, Activity activity) { final PorterDuffColorFilter colorFilter = new PorterDuffColorFilter(toolbarIconsColor, PorterDuff.Mode.SRC_IN); for(int i = 0; i < toolbarView.getChildCount(); i++) { final View v = toolbarView.getChildAt(i); doColorizing(v, colorFilter, toolbarIconsColor); } //Step 3: Changing the color of title and subtitle. toolbarView.setTitleTextColor(toolbarIconsColor); toolbarView.setSubtitleTextColor(toolbarIconsColor); } public static void doColorizing(View v, final ColorFilter colorFilter, int toolbarIconsColor){ if(v instanceof ImageButton) { ((ImageButton)v).getDrawable().setAlpha(255); ((ImageButton)v).getDrawable().setColorFilter(colorFilter); } if(v instanceof ImageView) { ((ImageView)v).getDrawable().setAlpha(255); ((ImageView)v).getDrawable().setColorFilter(colorFilter); } if(v instanceof AutoCompleteTextView) { ((AutoCompleteTextView)v).setTextColor(toolbarIconsColor); } if(v instanceof TextView) { ((TextView)v).setTextColor(toolbarIconsColor); } if(v instanceof EditText) { ((EditText)v).setTextColor(toolbarIconsColor); } if (v instanceof ViewGroup){ for (int lli =0; lli< ((ViewGroup)v).getChildCount(); lli ++){ doColorizing(((ViewGroup)v).getChildAt(lli), colorFilter, toolbarIconsColor); } } if(v instanceof ActionMenuView) { for(int j = 0; j < ((ActionMenuView)v).getChildCount(); j++) { //Step 2: Changing the color of any ActionMenuViews - icons that //are not back button, nor text, nor overflow menu icon. final View innerView = ((ActionMenuView)v).getChildAt(j); if(innerView instanceof ActionMenuItemView) { int drawablesCount = ((ActionMenuItemView)innerView).getCompoundDrawables().length; for(int k = 0; k < drawablesCount; k++) { if(((ActionMenuItemView)innerView).getCompoundDrawables()[k] != null) { final int finalK = k; //Important to set the color filter in seperate thread, //by adding it to the message queue //Won't work otherwise. //Works fine for my case but needs more testing ((ActionMenuItemView) innerView).getCompoundDrawables()[finalK].setColorFilter(colorFilter); // innerView.post(new Runnable() { // @Override // public void run() { // ((ActionMenuItemView) innerView).getCompoundDrawables()[finalK].setColorFilter(colorFilter); // } // }); } } } } } } } 

luego refiérase a él en su archivo de diseño. Ahora puedes establecer un color personalizado usando

 toolbar.setItemColor(Color.Red); 

Fuentes:

Encontré la información para hacer esto aquí: Cómo cambiar dinámicamente los icons de la barra de herramientas de Android en color

y luego lo edité , lo mejoré y lo publiqué aquí: GitHub: AndroidDynamicToolbarItemColor

Esto es lo que puedes hacer:

escriba un archivo en una carpeta dibujable, asígnele el nombre background.xml

     

luego configura tu diseño (o lo que sea que sea el caso) android:background="@drawable/background"

al configurar su tema, este color representaría lo mismo.

de una actividad que puedes hacer:

 getWindow().setStatusBarColor(i color);