我希望能够在运行时覆盖我的应用程序资源,例如R.colour.brand_colour或R.drawable.ic_action_start。我的应用程序连接到CMS系统,该系统将提供商标颜色和图像。应用下载了CMS数据后,就需要能够重新设置外观。
我知道您要说的是-无法在运行时覆盖资源。
除了有点。特别是,我从2012年发现了这个学士学位论文,它解释了基本概念ContextWrapper
-androidextends中的Activity类,其中包含attachBaseContext方法。您可以重写attachBaseContext,以用自己的自定义类包装Context,该自定义类将覆盖诸如getColor和getDrawable之类的方法。您自己的getColor实现可以根据需要查找颜色。该书法库使用类似的方法注入定制LayoutInflator可以处理负荷自定义字体。
我创建了一个简单的Activity,使用此方法来覆盖颜色的加载。
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(new CmsThemeContextWrapper(newBase));
}
private class CmsThemeContextWrapper extends ContextWrapper{
private Resources resources;
public CmsThemeContextWrapper(Context base) {
super(base);
resources = new Resources(base.getAssets(), base.getResources().getDisplayMetrics(), base.getResources().getConfiguration()){
@Override
public void getValue(int id, TypedValue outValue, boolean resolveRefs) throws NotFoundException {
Log.i("ThemeTest", "Getting value for resource " + getResourceName(id));
super.getValue(id, outValue, resolveRefs);
if(id == R.color.theme_colour){
outValue.data = Color.GREEN;
}
}
@Override
public int getColor(int id) throws NotFoundException {
Log.i("ThemeTest", "Getting colour for resource " + getResourceName(id));
if(id == R.color.theme_colour){
return Color.GREEN;
}
else{
return super.getColor(id);
}
}
};
}
@Override
public Resources getResources() {
return resources;
}
}
}
问题是,它不起作用!日志记录显示了对加载资源的调用,例如layout / activity_main和mipmap / ic_launcher,但是从未加载color / theme_colour。似乎上下文用于创建窗口和操作栏,而不是活动的内容视图。
我的问题是-如果不是活动上下文,布局充气机将从何处加载资源?我也想知道-在运行时是否有一种可行的方法来覆盖颜色和可绘制对象的加载?
我知道有可能以其他方式从CMS数据中为应用程序主题化-例如,我们可以创建一个方法,getCMSColour(String key)
然后在内部创建onCreate()
一堆代码,如下所示:
myTextView.setTextColour(getCMSColour("heading_text_colour"))
对于可绘制对象,字符串等可以采用类似的方法。但是,这将导致大量的样板代码-所有这些都需要维护。修改UI时,很容易忘记在特定视图上设置颜色。
包装上下文以返回我们自己的自定义值比较“干净”,不容易损坏。在探索替代方法之前,我想了解为什么它不起作用。
虽然“动态覆盖资源”似乎可以解决您的问题,但是我相信一种更干净的方法是使用官方数据绑定实现https://developer.android.com/tools/data-binding/guide.html,因为并不意味着破解android方式。
您可以使用POJO传递品牌设置。@color/button_color
您可以@{brandingConfig.buttonColor}
使用所需的值编写和绑定视图,而不必像使用静态样式那样。具有适当的活动层次结构,它不应添加太多样板。
这还使您能够更改布局上更复杂的元素,即:根据品牌设置在其他布局上包括不同的布局,从而使UI高度可配置,而无需花费太多精力。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句