Как _really_ программно изменить основной и акцентный цвет в Android Lollipop?

Прежде всего, этот вопрос задает очень похожий вопрос. Однако мой вопрос имеет тонкую разницу.

Я хотел бы знать, можно ли программно изменить атрибут colorPrimary темы на произвольный цвет?

Так, например, мы имеем:

 <style name="AppTheme" parent="android:Theme.Material.Light"> <item name="android:colorPrimary">#ff0000</item> <item name="android:colorAccent">#ff0000</item> </style> 

Во время выполнения пользователь решает, что хочет использовать #ccffff в качестве основного цвета. Конечно, я не могу создавать темы для всех возможных цветов.

Я не возражаю, если мне приходится делать хакерские вещи, например, полагаться на частные внутренние компоненты Android, если они работают с использованием общедоступного SDK.

Моя цель состоит в том, чтобы в конечном итоге ActionBar и все виджеты, такие как CheckBox использовали этот основной цвет.

Solutions Collecting From Web of "Как _really_ программно изменить основной и акцентный цвет в Android Lollipop?"

Темы неизменны, вы не можете.

Я прочитал комментарии о приложении для контактов и о том, как использовать тему для каждого контакта.

Возможно, приложение для контактов имеет некоторые предопределенные темы (для каждого основного основного материала здесь: http://www.google.com/design/spec/style/color.html ).

Вы можете применить тему до метода setContentView внутри метода onCreate.

Затем приложение-приложение может произвольно применять тему для каждого пользователя.

Этот метод:

 setTheme(R.style.MyRandomTheme); 

Но этот метод имеет проблему, например, он может изменять цвет панели инструментов, цвет эффекта прокрутки, цвет пульсации и т. Д., Но он не может изменить цвет строки состояния и цвет панели навигации (если вы тоже хотите его изменить).

Затем для решения этой проблемы вы можете использовать метод до и:

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

Этот два метода изменяет цвет навигации и строки состояния. Помните, что если вы установите прозрачную навигационную панель, вы не сможете изменить ее цвет.

Это должен быть конечный код:

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

Вы можете использовать переключатель и генерировать случайное число, чтобы использовать случайные темы, или, как в приложении для контактов, каждый контакт, вероятно, имеет предопределенный номер.

Образец темы:

 <style name="MyRandomTheme" parent="Theme.AppCompat.NoActionBar"> <!-- Customize your theme here. --> <item name="colorPrimary">@color/myrandomcolor1</item> <item name="colorPrimaryDark">@color/myrandomcolor2</item> <item name="android:navigationBarColor">@color/myrandomcolor1</item> </style> 

Извините за мой английский.

Вы можете использовать Theme.applyStyle для изменения темы во время выполнения, применяя к ней еще один стиль.

Допустим, у вас есть эти определения стиля:

 <style name="DefaultTheme" parent="Theme.AppCompat.Light"> <item name="colorPrimary">@color/md_lime_500</item> <item name="colorPrimaryDark">@color/md_lime_700</item> <item name="colorAccent">@color/md_amber_A400</item> </style> <style name="OverlayPrimaryColorRed"> <item name="colorPrimary">@color/md_red_500</item> <item name="colorPrimaryDark">@color/md_red_700</item> </style> <style name="OverlayPrimaryColorGreen"> <item name="colorPrimary">@color/md_green_500</item> <item name="colorPrimaryDark">@color/md_green_700</item> </style> <style name="OverlayPrimaryColorBlue"> <item name="colorPrimary">@color/md_blue_500</item> <item name="colorPrimaryDark">@color/md_blue_700</item> </style> 

Теперь вы можете исправлять свою тему во время выполнения следующим образом:

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

Конечно, это нельзя использовать для указания произвольного цвета, то есть одного из 16 миллионов (256 3 ) цветов. Но если вы пишете небольшую программу, которая генерирует определения стиля и код Java для вас, то должно быть возможно что-то вроде одного из 512 (8 3 ).

Интересно то, что вы можете использовать разные наложения стиля для разных аспектов вашей темы. Просто добавьте несколько описаний наложения для colorAccent например. Теперь вы можете комбинировать различные значения для основного цвета и цвета акцента почти произвольно.

Библиотека GreenMatter может помочь вам в достижении функциональности, которую вы ищете:

https://github.com/negusoft/GreenMatter

Я использовал код Данарка, но мне также нужно изменить фон 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)); } 

Это может быть не совсем то, что вы хотите, но этот ответ работает на меня.

Я также хотел бы увидеть этот метод, где вы устанавливаете один раз для всех своих действий. Но насколько я знаю, вы должны установить в каждом мероприятии, прежде чем показывать какие-либо мнения.

Для справки проверьте это:

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

Изменить (скопировано с этого форума):

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

Это то, что вы МОЖЕТЕ сделать:

Напишите файл в папке с возможностью переноса, давайте назовите его background.xml

 <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" > <solid android:color="?attr/colorPrimary"/> </shape> 

Затем установите свой макет (или, что когда-либо случается). android:background="@drawable/background"

При настройке вашей темы этот цвет будет представлять собой то же самое.

ИСПОЛЬЗУЙТЕ ИНСТРУМЕНТ

Динамически настраивать динамический элемент панели инструментов можно, создав собственный класс панели инструментов:

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

Затем обратитесь к нему в файл макета. Теперь вы можете установить собственный цвет, используя

 toolbar.setItemColor(Color.Red); 

Источники:

Я нашел информацию, чтобы сделать это здесь: Как динамически изменить цвет значков панели инструментов Android

А затем я отредактировал его, улучшил его и разместил здесь: GitHub: AndroidDynamicToolbarItemColor

От деятельности, которую вы можете сделать:

 getWindow().setStatusBarColor(i color);