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

时间:2015-11-29 20:27:20

标签: android android-resources aapt

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

举个例子:

我调用了我的API并返回green,现在我想用ie(绿色Toolbar,绿色TextView颜色等加载我的应用),是可能的?

我的第一个想法是:

在名为colors.xml的{​​{1}}上创建一个项目,然后为其指定默认颜色,然后在我想要的任何地方使用此demo颜色(demoButton,然后我认为可以使用API​​的结果以编程方式更改此值,因此我不需要创建TextView或类似的东西,以避免更多代码。

正如@Y.S.对我说的那样

  

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

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

修改

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

首先,我有一个GlobalConstant和一个TextView,其中包含“your_special_color”,并且返回它我将Button置于如下:

GlobalConstant int

然后我尝试的是我的第一个case "your_special_color": return GlobalConstant.color; 有一个Activity和一个TextView,正如我之前说的那样,他们有颜色“your_special_color”,我不想改变它,但我Button上有一个Intent打开另一个Button,其中包含ActivityGlobalConstant.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));

5 个答案:

答案 0 :(得分:56)

您可以创建一个扩展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,则可以以编程方式更改主题(即使主题是不可变的)。如果需要,请下载该应用程序,并查看如何根据首选项设置主要,重音和背景颜色。

答案 1 :(得分:25)

如果您查看Accessing Resources文档,它说的是......

  

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

此外,

  

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

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

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

为了减少需要添加到项目中的代码量,还有一种替代方法。我之前使用的calligraphy library允许我修改字体样式&amp;整个应用程序的颜色。这对你来说可能有一些好处,请查看......

答案 2 :(得分:10)

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

请参阅How to use SharedPreferences in Android to store, fetch and edit values

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

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

答案 3 :(得分:10)

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中的RedActivityActivity.onCreate个样式之间切换:

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

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

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

应用程序/ SRC /主/ RES / colors.xml

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

应用程序/ SRC / buildVariant / RES / colors.xml

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

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

搜索&#34;构建变体&#34;这里http://developer.android.com/tools/building/configuring-gradle.html

答案 4 :(得分:3)

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