以编程方式更改从API响应获得的颜色资源的值

时间:2020-12-01 14:05:27

Let's say, on my API call I have a parameter that's called color. Is it possible to edit or modify an existent R.colors.color to assign the color from the API result?

比方说,在我的API调用中,我有一个名为color的参数。是否可以编辑或修改现有的R.colors.color以从API结果中分配颜色?

As an example:

举个例子:

I make a call to my API and it returns green, now I want to load my app with i.e (green Toolbar, green TextView color, etc.), is that possible?

我打电话给我的API,它返回绿色,现在我想加载我的应用程序,即(绿色工具栏,绿色TextView颜色等),这可能吗?

My first thought was:

我的第一个想法是:

Create a item on colors.xml called demo then assign it a default color, then use this demo color wherever I want (Button, TextView, etc.) Then I thought it could be possible to change this value programmatically with the result from the API so I wouldn't need to create a SharedPreferences or something like that and for avoiding more code.

在colors.xml上创建一个名为demo的项目,然后为它指定一个默认颜色,然后在任何我想要的地方使用这个演示颜色(Button,TextView等)然后我认为可以通过API的结果以编程方式更改此值所以我不需要创建一个SharedPreferences或类似的东西,以避免更多的代码。

As @Y.S. said to me

作为@ Y.S。对我说

Unfortunately, you WILL have to set the color of the text or view manually everywhere ... :(

不幸的是,你必须手动设置文本或视图的颜色...... :(

I would like if there is other way to do it, since I don't know how many Activities my project will contain, so if is there other way to do it I'm glad to hear other guesses.

我想如果有其他方法可以做到这一点,因为我不知道我的项目将包含多少活动,所以如果有其他方法可以做到这一点我很高兴听到其他猜测。

EDIT

I'm trying the @Jared Rummler answer and maybe i'm doing something wrong... I've created a simple Json and I put on my Assets I parse the Json and I put it on a GlobalConstant then I made a "simple app".

我正在尝试@Jared Rummler的答案,也许我做错了什么......我创建了一个简单的Json,我把我的资产放在我解析Json上,然后把它放在GlobalConstant上然后我做了一个“简单的”应用”。

First of all I have a TextView and a Button which contains the "your_special_color", and the return of it I put the GlobalConstant int as follows :

首先,我有一个TextView和一个包含“your_special_color”的Button,并返回它我将GlobalConstant设置为int,如下所示:

case "your_special_color":                            return GlobalConstant.color; 

Then what I tried is my first Activity has 1 TextView and 1 Button as I said before and they have the color "your_special_color" that I don't want to change it, BUT I have an Intent on my Button to open the other Activity that contains the same but with the GlobalConstant.color and it doesn't change.

然后我尝试的是我的第一个Activity有一个TextView和一个按钮,正如我之前所说,他们有颜色“your_special_color”,我不想改变它,但我在我的按钮上有一个Intent打开另一个Activity,包含相同但使用GlobalConstant.color并且它不会更改。

I tried it doing this (my second Activity):

我试过这样做(我的第二个活动):

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

Did I miss something?

我错过了什么?

Oh.. I figured it out I guess is doing this on my MainActivity2 ?

哦..我想出来我想在我的MainActivity2上这样做?

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

5 个解决方案

#1


22  

If you take a look at the Accessing Resources document, what it says is that ...

如果您查看访问资源文档,它说的是......

Once you provide a resource in your application, you can apply it by referencing its resource ID. All resource IDs are defined in your project's R class, which the aapt tool automatically generates.

在应用程序中提供资源后,可以通过引用其资源ID来应用它。所有资源ID都在项目的R类中定义,aapt工具会自动生成。

Furthermore,

When your application is compiled, aapt generates the R class, which contains resource IDs for all the resources in your res/ directory. For each type of resource, there is an R subclass (for example, R.drawable for all drawable resources), and for each resource of that type, there is a static integer (for example, R.drawable.icon). This integer is the resource ID that you can use to retrieve your resource.

编译应用程序时,aapt会生成R类,其中包含res /目录中所有资源的资源ID。对于每种类型的资源,都有一个R子类(例如,所有可绘制资源的R.drawable),对于该类型的每个资源,都有一个静态整数(例如,R.drawable.icon)。此整数是可用于检索资源的资源ID。

What this is saying, essentially, is that pretty much everything held as a resource in the res/ directory is compiled and referenced as an unchangeable constant. It is for this reason that the values of resource elements cannot be changed programmatically/at runtime, because they are compiled. As opposed to local/global variables & SharedPreferences, resource elements are represented in program memory as fixed, unchangeable objects. They are held in a special read-only region of program memory. In this regard, see also Changing value of R.String Programmatically.

实际上,这就是说,作为res /目录中的资源保存的几乎所有内容都被编译并作为不可更改的常量引用。出于这个原因,资源元素的值不能以编程方式/在运行时更改,因为它们是经过编译的。与本地/全局变量和SharedPreferences相反,资源元素在程序存储器中表示为固定的,不可更改的对象。它们保存在程序存储器的特殊只读区域中。在这方面,另请参阅以编程方式更改R.String的值。

What you can do is, to avoid using the same code at a thousand places in your project, create a common function that changes the value of the color in the SharedPreferences and use this method everywhere. I'm sure you knew this already, of course.

你可以做的是,为了避免在项目的一千个地方使用相同的代码,创建一个通用函数来改变SharedPreferences中颜色的值,并在任何地方使用这个方法。当然,我确定你已经知道了。

To reduce the amount of code you need to add to the project, there is an alternative. I have previously used the calligraphy library which allowed me to fix the font style & color throughout the app. This may be of some good use to you, check it out ...

为了减少需要添加到项目中的代码量,还有一种替代方法。我之前使用过书法库,这使我能够在整个应用程序中修复字体样式和颜色。这对你来说可能有一些好用,看看吧......

#2


48  

You can create a class which extends Resources and override the methods getColor(int) and getColor(int, Theme).

您可以创建一个扩展Resources的类,并重写方法getColor(int)和getColor(int,Theme)。

Example:

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

This is the approach I have used in one of my apps, Root Check. If you override getResources in your activities and main application class you can change the theme programmatically (even though themes are immutable). If you want, download the app and see how you can set the primary, accent, and background colors from preferences.

这是我在我的一个应用程序Root Check中使用的方法。如果在活动和主应用程序类中覆盖getResources,则可以以编程方式更改主题(即使主题是不可变的)。如果需要,请下载该应用程序,并查看如何根据首选项设置主要,重音和背景颜色。

#3


10  

R class is not supposed to be edited. It merely contains references to your resources.

R类不应该被编辑。它只包含对您资源的引用。

You will need to set it manually. However, to reduce the burden of setting it manually you can try to use special libraries for preference saving, for instance:

您需要手动设置它。但是,为了减少手动设置它的负担,您可以尝试使用特殊库来保存首选项,例如:

(full list of similar libraries https://android-arsenal.com/tag/75)

(类似库的完整列表https://android-arsenal.com/tag/75)


Also, you might want to think about another way of applying styles and passing parameters - consider you would want to add some other parameters like height, width etc. For that purpose, you can define custom attribute in themes.xml/styles.xml:

此外,您可能想要考虑应用样式和传递参数的另一种方法 - 考虑您要添加一些其他参数,如高度,宽度等。为此,您可以在themes.xml / styles.xml中定义自定义属性:

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

then define styles:

然后定义样式:

<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>

then use that color in your xml like this:

然后在你的xml中使用这种颜色,如下所示:

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

and switch between GreenActivity and RedActivity styles in Activity.onCreate:

并在Activity.onCreate中切换GreenActivity和RedActivity样式:

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

With the above approach, you will be able to easily configure your styles in xml and it should be less code and easier to refactor in future. (You will still need to have one variable in preference to save whether you have green or red style)

使用上述方法,您将能够在xml中轻松配置样式,并且应该是更少的代码,并且将来更容易重构。 (您仍然需要优先选择一个变量来保存您是否有绿色或红色样式)


Another way, if you want to show demos of your app with different colors is to use build variants / flavors for loading your app with different colors and styles (it is for build time - not runtime):

另一种方式,如果你想用不同的颜色显示你的应用程序的演示是使用构建变体/口味来加载你的应用程序与不同的颜色和样式(它是为了构建时间 - 而不是运行时):

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>

Now you can quickly switch between "main" and "buildVariant" in Build Variants menu and launch your app with different "demo" colors. The same way you can customize a lot of other attributes.

现在,您可以在Build Variants菜单中快速切换“main”和“buildVariant”,并使用不同的“演示”颜色启动您的应用程序。您可以使用相同的方式自定义许多其他属性。

Search for "Build Variants" here http://developer.android.com/tools/building/configuring-gradle.html

在这里搜索“Build Variants”http://developer.android.com/tools/building/configuring-gradle.html

#4


8  

You can't change an app's resources, they are all constants. Instead you can save your color in SharedPrefences and use the color from there.

您无法更改应用程序的资源,它们都是常量。相反,您可以在SharedPrefences中保存颜色并使用那里的颜色。

See How to use SharedPreferences in Android to store, fetch and edit values.

请参阅如何在Android中使用SharedPreferences来存储,获取和编辑值。

If your app already has a R.color.green defined and you just want to access it based on what API returned you use:

如果您的应用已经定义了R.color.green,您只想根据您使用的API返回来访问它:

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

#5


3  

store hex color codes into sharedpreferences and then use parsecolor function store your all hexcodes of colors into sessions as a string and whenever you want to change color of perticular button ,textview..just retrive that color code from session and use it as
for ex.
session.setString("white","#FFFFFF");String colorname=session.getString("white");yourtextview.setBackgroundColor(Color.parseColor(colorname);

将十六进制颜色代码存储到共享首选项中,然后使用parsecolor函数将所有颜色的十六进制数存储到会话中作为字符串,每当您想要更改特定按钮的颜色时,textview ..只需从会话中检索该颜色代码并将其用作ex。 session.setString(“white”,“#FFFFFF”); String colorname = session.getString(“white”); yourtextview.setBackgroundColor(Color.parseColor(colorname);

#1


22  

If you take a look at the Accessing Resources document, what it says is that ...

如果您查看访问资源文档,它说的是......

Once you provide a resource in your application, you can apply it by referencing its resource ID. All resource IDs are defined in your project's R class, which the aapt tool automatically generates.

在应用程序中提供资源后,可以通过引用其资源ID来应用它。所有资源ID都在项目的R类中定义,aapt工具会自动生成。

Furthermore,

When your application is compiled, aapt generates the R class, which contains resource IDs for all the resources in your res/ directory. For each type of resource, there is an R subclass (for example, R.drawable for all drawable resources), and for each resource of that type, there is a static integer (for example, R.drawable.icon). This integer is the resource ID that you can use to retrieve your resource.

编译应用程序时,aapt会生成R类,其中包含res /目录中所有资源的资源ID。对于每种类型的资源,都有一个R子类(例如,所有可绘制资源的R.drawable),对于该类型的每个资源,都有一个静态整数(例如,R.drawable.icon)。此整数是可用于检索资源的资源ID。

What this is saying, essentially, is that pretty much everything held as a resource in the res/ directory is compiled and referenced as an unchangeable constant. It is for this reason that the values of resource elements cannot be changed programmatically/at runtime, because they are compiled. As opposed to local/global variables & SharedPreferences, resource elements are represented in program memory as fixed, unchangeable objects. They are held in a special read-only region of program memory. In this regard, see also Changing value of R.String Programmatically.

实际上,这就是说,作为res /目录中的资源保存的几乎所有内容都被编译并作为不可更改的常量引用。出于这个原因,资源元素的值不能以编程方式/在运行时更改,因为它们是经过编译的。与本地/全局变量和SharedPreferences相反,资源元素在程序存储器中表示为固定的,不可更改的对象。它们保存在程序存储器的特殊只读区域中。在这方面,另请参阅以编程方式更改R.String的值。

What you can do is, to avoid using the same code at a thousand places in your project, create a common function that changes the value of the color in the SharedPreferences and use this method everywhere. I'm sure you knew this already, of course.

你可以做的是,为了避免在项目的一千个地方使用相同的代码,创建一个通用函数来改变SharedPreferences中颜色的值,并在任何地方使用这个方法。当然,我确定你已经知道了。

To reduce the amount of code you need to add to the project, there is an alternative. I have previously used the calligraphy library which allowed me to fix the font style & color throughout the app. This may be of some good use to you, check it out ...

为了减少需要添加到项目中的代码量,还有一种替代方法。我之前使用过书法库,这使我能够在整个应用程序中修复字体样式和颜色。这对你来说可能有一些好用,看看吧......

#2


48  

You can create a class which extends Resources and override the methods getColor(int) and getColor(int, Theme).

您可以创建一个扩展Resources的类,并重写方法getColor(int)和getColor(int,Theme)。

Example:

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

This is the approach I have used in one of my apps, Root Check. If you override getResources in your activities and main application class you can change the theme programmatically (even though themes are immutable). If you want, download the app and see how you can set the primary, accent, and background colors from preferences.

这是我在我的一个应用程序Root Check中使用的方法。如果在活动和主应用程序类中覆盖getResources,则可以以编程方式更改主题(即使主题是不可变的)。如果需要,请下载该应用程序,并查看如何根据首选项设置主要,重音和背景颜色。

#3


10  

R class is not supposed to be edited. It merely contains references to your resources.

R类不应该被编辑。它只包含对您资源的引用。

You will need to set it manually. However, to reduce the burden of setting it manually you can try to use special libraries for preference saving, for instance:

您需要手动设置它。但是,为了减少手动设置它的负担,您可以尝试使用特殊库来保存首选项,例如:

(full list of similar libraries https://android-arsenal.com/tag/75)

(类似库的完整列表https://android-arsenal.com/tag/75)


Also, you might want to think about another way of applying styles and passing parameters - consider you would want to add some other parameters like height, width etc. For that purpose, you can define custom attribute in themes.xml/styles.xml:

此外,您可能想要考虑应用样式和传递参数的另一种方法 - 考虑您要添加一些其他参数,如高度,宽度等。为此,您可以在themes.xml / styles.xml中定义自定义属性:

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

then define styles:

然后定义样式:

<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>

then use that color in your xml like this:

然后在你的xml中使用这种颜色,如下所示:

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

and switch between GreenActivity and RedActivity styles in Activity.onCreate:

并在Activity.onCreate中切换GreenActivity和RedActivity样式:

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

With the above approach, you will be able to easily configure your styles in xml and it should be less code and easier to refactor in future. (You will still need to have one variable in preference to save whether you have green or red style)

使用上述方法,您将能够在xml中轻松配置样式,并且应该是更少的代码,并且将来更容易重构。 (您仍然需要优先选择一个变量来保存您是否有绿色或红色样式)


Another way, if you want to show demos of your app with different colors is to use build variants / flavors for loading your app with different colors and styles (it is for build time - not runtime):

另一种方式,如果你想用不同的颜色显示你的应用程序的演示是使用构建变体/口味来加载你的应用程序与不同的颜色和样式(它是为了构建时间 - 而不是运行时):

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>

Now you can quickly switch between "main" and "buildVariant" in Build Variants menu and launch your app with different "demo" colors. The same way you can customize a lot of other attributes.

现在,您可以在Build Variants菜单中快速切换“main”和“buildVariant”,并使用不同的“演示”颜色启动您的应用程序。您可以使用相同的方式自定义许多其他属性。

Search for "Build Variants" here http://developer.android.com/tools/building/configuring-gradle.html

在这里搜索“Build Variants”http://developer.android.com/tools/building/configuring-gradle.html

#4


8  

You can't change an app's resources, they are all constants. Instead you can save your color in SharedPrefences and use the color from there.

您无法更改应用程序的资源,它们都是常量。相反,您可以在SharedPrefences中保存颜色并使用那里的颜色。

See How to use SharedPreferences in Android to store, fetch and edit values.

请参阅如何在Android中使用SharedPreferences来存储,获取和编辑值。

If your app already has a R.color.green defined and you just want to access it based on what API returned you use:

如果您的应用已经定义了R.color.green,您只想根据您使用的API返回来访问它:

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

#5


3  

store hex color codes into sharedpreferences and then use parsecolor function store your all hexcodes of colors into sessions as a string and whenever you want to change color of perticular button ,textview..just retrive that color code from session and use it as
for ex.
session.setString("white","#FFFFFF");String colorname=session.getString("white");yourtextview.setBackgroundColor(Color.parseColor(colorname);

将十六进制颜色代码存储到共享首选项中,然后使用parsecolor函数将所有颜色的十六进制数存储到会话中作为字符串,每当您想要更改特定按钮的颜色时,textview ..只需从会话中检索该颜色代码并将其用作ex。 session.setString(“white”,“#FFFFFF”); String colorname = session.getString(“white”); yourtextview.setBackgroundColor(Color.parseColor(colorname);