Програмно змінити значення кольорового ресурсу, отриманого в результаті відповіді API


79

Скажімо, у моєму виклику API у мене є параметр, який називається color. Чи можна редагувати або модифікувати існуючий R.colors.colorдля призначення кольору з результату API?

Як приклад:

Я телефоную до свого API, і він повертається green, тепер я хочу завантажити свою програму тобто (зелений Toolbar, зелений TextViewколір тощо), чи можливо це?

Моя перша думка була:

Створіть елемент на colors.xmlвикликаному, demoпотім призначте йому колір за замовчуванням, а потім використовуйте цей demoколір, де я хочу ( Button, TextViewтощо) Тоді я подумав, що це можливо програмно змінити це значення з результатом з API, тому мені не потрібно буде створити SharedPreferencesабо щось подібне і для уникнення додаткового коду.

Як мені сказав @YS

На жаль, вам доведеться встановлювати колір тексту або переглядати скрізь вручну ... :(

Я хотів би, щоб це було іншим способом, оскільки я не знаю, скільки Activitiesміститиме мій проект, тому, якщо є інший спосіб це зробити, я радий почути інші здогади.

РЕДАГУВАТИ

Я намагаюся відповісти @Jared Rummler, і, можливо, я роблю щось не так ... Я створив простий Jsonі розмістив свої активи, аналізую Jsonі ставлю наGlobalConstant потім зробив "просте додаток".

Перш за все, у мене є а TextViewі a, Buttonяке містить "ваш_спеціальний_барв", а повернення його я поміщаю GlobalConstant intнаступним чином:

case "your_special_color":                
            return GlobalConstant.color; 

Тоді те, що я спробував, це мій перший Activityмає 1 TextViewі 1, Buttonяк я вже говорив раніше, і вони мають колір "your_special_color", що я не хочу його змінювати, АЛЕ я маю Intentна своєму, Buttonщоб відкрити інший, Activityякий містить те саме, але зGlobalConstant.color і це не змінюється.

Я спробував це зробити (моя друга діяльність):

public class Main2Activity extends AppCompatActivity {
private Res res;
@Override public Resources getResources() {
    if (res == null) {
        res = new Res(super.getResources());
    }
    return res;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main2);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
}

Я щось пропустив?

О .. Я зрозумів це, я думаю, робить це на моєму MainActivity2?

 Button btn = (Button)findViewById(R.id.button2);
 btn.setBackgroundColor(res.getColor(R.color.your_special_color));

1
Ви отримали якесь рішення щодо цього?
Tixeon

1
Гей! Ви нарешті вирішили це? Я стикаюся з подібною проблемою!
Рохітеш

Дотримуйтесь рішення Джареда, воно працює, я думаю
Skizo-ozᴉʞS

1
Перевірте Cyanea, щоб динамічно змінювати основні та акцентні
Jared Rummler

@JaredRummler Чи можете ви додати допис, щоб пояснити, як працює Cyanea? Дякую.
Q Locker

Відповіді:


27

Якщо ви подивитесь на документ доступу до ресурсів , там сказано, що ...

Щойно ви надасте ресурс у своїй програмі, ви можете застосувати його, посилаючись на його ідентифікатор ресурсу. Усі ідентифікатори ресурсів визначаються у Rкласі вашого проекту , який aaptінструмент автоматично генерує.

Крім того,

Коли ваша програма компілюється , aaptгенерує Rклас, який містить ідентифікатори ресурсів для всіх ресурсів у вашому res/ каталозі. Для кожного типу ресурсу існує Rпідклас (наприклад, R.drawableдля всіх ресурсів , які можна залучати), а для кожного ресурсу цього типу існує статичне ціле число (наприклад, R.drawable.icon). Це ціле число - це ідентифікатор ресурсу, який ви можете використовувати для отримання ресурсу.

Те , що це говорить, по суті, є те , що майже всі , що провів в якості ресурсу в res/каталозі компілюється і посилання в якості незмінного константи. Саме з цієї причини значення елементів ресурсів не можуть бути змінені програмно / під час виконання, оскільки вони компілюються . На відміну від локальних / глобальних змінних & SharedPreferences, елементи ресурсів представлені в пам'яті програми як фіксовані незмінні об'єкти. Вони містяться в спеціальній області, лише для читання, пам'яті програм. У цьому відношенні див. Також Зміна значення R.String програмно .

Що ви можете зробити, це, щоб уникнути використання одного і того ж коду в тисячі місць у вашому проекті, створити загальну функцію, яка змінює значення кольору в SharedPreferencesі використовувати цей метод скрізь. Я впевнений, ти це вже знав, звичайно.

Щоб зменшити кількість коду, який потрібно додати до проекту, існує альтернатива. Раніше я використовував бібліотеку каліграфії, що дозволило мені зафіксувати стиль і колір шрифту у всій програмі. Це може вам корисно скористатися, перевірте ...


Отже, ти кажеш мені, що це неможливо зробити ...? Тоді мені доведеться створити на кожному фрагменті кожного виду діяльності колір зображення?
Skizo-ozᴉʞS

Правильно, ви не можете цього робити. Але вам не потрібно створювати колір неодноразово, ви можете створити його в загальному базовому класі і зберегти значення як глобальну змінну, яку можна використовувати скрізь. На жаль, ви БУДЕТЕ повинні встановити колір тексту або подання вручну всюди ... :(
YS

Так, що я мав на увазі ... Я можу зберегти значення на sharedpref, потім створити globalclaas, щоб оголосити колір, але потім ... Весь фон набору setcolor потрібен добре ... Я спробую десь знайти інше рішення, якщо Я не знаходжу жодного, я зроблю те, що ти скажеш @YS
Skizo-ozᴉʞS

За допомогою цього з de api я також можу отримати шрифт?
Skizo-ozᴉʞS

Ви маєте на увазі, що я можу призначити програмі шрифт, а потім оголосити колір?
Skizo-ozᴉʞS

69

Ви можете створити клас, який розширює Resourcesі замінює методи getColor(int)таgetColor(int, Theme) .

Приклад:

colors.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="your_special_color">#FF0099CC</color>
</resources>

Res.java

public class Res extends Resources {

    public Res(Resources original) {
        super(original.getAssets(), original.getDisplayMetrics(), original.getConfiguration());
    }

    @Override public int getColor(int id) throws NotFoundException {
        return getColor(id, null);
    }

    @Override public int getColor(int id, Theme theme) throws NotFoundException {
        switch (getResourceEntryName(id)) {
            case "your_special_color":
                // You can change the return value to an instance field that loads from SharedPreferences.
                return Color.RED; // used as an example. Change as needed.
            default:
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    return super.getColor(id, theme);
                }
                return super.getColor(id);
        }
    }
}

BaseActivity.java

public class BaseActivity extends AppCompatActivity {

    ...

    private Res res;

    @Override public Resources getResources() {
        if (res == null) {
            res = new Res(super.getResources());
        }
        return res;
    }

    ...

}

Це підхід, який я використав в одному зі своїх додатків, Root Check . Якщо ви перевизначаєте getResourcesсвої дії та основний клас додатків, ви можете програмно змінити тему (навіть якщо теми незмінні). Якщо хочете, завантажте програму та подивіться, як ви можете встановити основний, акцентний та фоновий кольори з параметрів.


спасибі за відповідь, хлопець! Я уважно прочитаю це і спробую зрозуміти, чи це те, що мені потрібно, з цим ви думаєте, якщо я отримаю колір (int) від виклику API і я використовую його на всіх своїх фонах, стилях тощо ... мій колір за замовчуванням він покаже колір API?
Skizo-ozᴉʞS

3
Я не буду доступний ще 6 годин. Не соромтеся надсилати мені електронного листа, і я допоможу вам. jared.rummler@gmail.com
Джаред Раммлер

9
Вибачте, хлопці, але це заразDEPECRATED
Arav K.

1
getColor (int, Theme) не дзвонить
учень

2
Я написав бібліотеку, яка динамічно змінює фон, основний та акцентний кольори програми. Наразі бібліотека не працює, але, сподіваюся, я зможу нею поділитися незабаром. Наведений вище код не буде працювати на Android 6.0+, оскільки в Ресурси було внесено багато змін. Крім того, я більше не є власником програми Root Check, зв’язаної у відповіді.
Джаред Раммлер,

13

Rклас не повинен редагуватися. Він просто містить посилання на ваші ресурси.

Вам потрібно буде встановити його вручну. Однак, щоб зменшити навантаження на встановлення вручну, можна спробувати використовувати спеціальні бібліотеки для збереження переваг, наприклад:

(повний список подібних бібліотек https://android-arsenal.com/tag/75 )


Крім того, ви можете подумати про інший спосіб застосування стилів та передачі параметрів - подумайте, чи хочете ви додати деякі інші параметри, такі як висота, ширина тощо. Для цього ви можете визначити власний атрибут у themes.xml / styles.xml:

<attr name="demoColor" format="reference|color" />

потім визначте стилі:

<style name="BaseActivity">
</style>
<style name="GreenActivity" parent="@style/BaseActivity">
    <item name="demoColor">#00cd00</item>
</style>
<style name="RedActivity" parent="@style/BaseActivity">
    <item name="demoColor">#ff0000</item>
</style>

тоді використовуйте цей колір у своєму xml так:

... android:background="?demoColor" ...

і перемикатися між GreenActivityта RedActivityстилями в Activity.onCreate:

setTheme(isGreenStyle() ? R.style.GreenActivity : R.style.RedActivity)
setContentView(...)

За допомогою вищезазначеного підходу ви зможете легко налаштувати свої стилі в xml, і це повинно мати менше коду і легше рефакторити в майбутньому. (Вам все одно знадобиться одна змінна, щоб зберегти, чи маєте ви зелений чи червоний стиль)


Інший спосіб, якщо ви хочете показати демонстраційні програми вашого додатка з різними кольорами, - це використовувати варіанти / аромати збірки для завантаження програми з різними кольорами та стилями (це для часу збірки, а не для виконання):

app / src / main / res / colors.xml

<resources>
    <color name="demoColor">#00cd00</color>
</resources>

app / src / buildVariant / res / colors.xml

<resources>
    <color name="demoColor">#ff0000</color>
</resources>

Тепер ви можете швидко перемикатися між "головним" та "buildVariant" у меню "Варіанти побудови" та запускати програму з різними "демонстраційними" кольорами. Таким же чином ви можете налаштувати багато інших атрибутів.

Шукайте "Варіанти збірки" тут http://developer.android.com/tools/building/configuring-gradle.html


О, не чув про це ... Тож я можу змінити значення програмно, якщо використовую buildvariant?
Skizo-ozᴉʞS

Варіанти / аромати збірки @Skizo не призначені для програмної зміни значення - вони дозволяють створювати та запускати програму з різними стилями / кольорами / ресурсами. Здається, я пропустив "програмно" частину з ваших запитань :) Трохи оновлю свою відповідь. Було б корисно, якщо б ви могли вказати реальне використання функціоналу, який ви намагаєтесь реалізувати. Можливо, є кращий спосіб це зробити.
GregoryK

Ну, я просто хочу зберегти колір, а не стиль.
Skizo-ozᴉʞS

Розумію. Додано пару бібліотек уподобань, тому ви можете розглянути можливість їх використання, оскільки вони дозволяють пов’язати налаштування - це може допомогти зі зменшенням коду.
GregoryK

Це саме те, що я шукав !!! Ти геній! Це дає вам можливість використовувати кольори в макетах і в коді. Ось приклад добре використовувати його в коді: stackoverflow.com/questions/17277618 / ...
bentzy

10

Ви не можете змінити ресурси програми, вони всі є константами. Натомість ви можете зберегти свій колір у SharedPrefences і використовувати його там.

Дізнайтеся, як використовувати SharedPreferences в Android для зберігання, отримання та редагування значень .

Якщо у вашому додатку вже визначено R.color.green, і ви просто хочете отримати до нього доступ на основі того, який повернутий API ви використовуєте:

int resourceID = getResources().getIdentifier("green", "color", getPackageName());

Я знаю, SharedPreferencesі я думаю, що ви мене не зрозуміли, я мав на увазі, що ви можете створити файл, який називається colors.xmlправильно? а потім на ньому створювати елементи з кольорами за допомогою HEX, тоді я хотів би знати, чи можу я програмно модифікувати це значення, щоб спочатку поставити демонстраційний колір, а потім справжній колір.
Skizo-ozᴉʞS

Ви не можете змінити вміст colors.xml під час виконання, натомість ви можете зберегти в ньому всі можливі кольори та використовувати getIdentifier для отримання кольору, поверненого API. Ви можете зберегти вибраний колір у SharedPref і отримати його пізніше в наступному сеансі до завершення виклику API
Sourabh

Так, але як встановити колір тексту textView або кнопки? якщо у мене є 10 переглядів тексту, і я хочу помістити їх у зелений текст, я повинен поставити setText (java) для кожного і призначити значення з SharedPreferences? ...
Skizo-ozᴉʞS

Так, це єдиний спосіб. І крім того, зміна ресурсів може пізніше призвести до різного роду плутанини у вашому додатку
Sourabh,

3

зберігайте шістнадцяткові коди кольорів у спільних налаштуваннях, а потім використовуйте функцію parsecolor, зберігайте всі шістнадцяткові кольори у сеансах у вигляді рядка, і всякий раз, коли ви хочете змінити колір перкулярної кнопки, textview .. просто витягніть цей колірний код із сеансу та використовуйте його як
для ex.
session.setString("white","#FFFFFF"); String colorname=session.getString("white");yourtextview.setBackgroundColor(Color.parseColor(colorname);


Що це? Чи можете ви трохи розширити свій код?
Skizo-ozᴉʞS
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.