在运行时覆盖资源

卢克·斯利曼

问题

我希望能够在运行时覆盖我的应用程序资源,例如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] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

在运行时添加字体资源

来自分类Dev

在运行时从资源导出图像

来自分类Dev

在运行时替换资源

来自分类Dev

在运行时覆盖常量值

来自分类Dev

在运行时在代码后面选择资源文件

来自分类Dev

在运行时列出可用的Android资源包?

来自分类Dev

如何在运行时更改SolidColorBrush资源的颜色?

来自分类Dev

在运行时本地化资源

来自分类Dev

WPF-在运行时更新静态资源值

来自分类Dev

在运行时切换UI资源

来自分类Dev

在运行时使用gdbus的systemd资源控制SetProperties

来自分类Dev

在运行时更新资源文件

来自分类Dev

如何在运行时更改可绘制资源?

来自分类Dev

在运行时编译库覆盖方法

来自分类Dev

在运行时覆盖Spring WebApp中的属性文件

来自分类Dev

在运行时重命名并更改android资源文件的文件夹位置

来自分类Dev

如何在运行时更改分配给容器的资源?

来自分类Dev

Java Spring + Jersey子资源:在运行时注入Constructor-arg

来自分类Dev

如何从可以在运行时使用的资源文件中创建和调用类对象?

来自分类Dev

嵌入式资源文件在运行时.Net 4不存在

来自分类Dev

如何在运行时将动态资源分配给WPF代码中的按钮

来自分类Dev

使用C ++ / boost在运行时从资源解析.ini文件

来自分类Dev

静态资源映像在运行时不出现(在设计时)

来自分类Dev

c#资源字典中的图像在运行时不显示

来自分类Dev

如何在运行时访问和修改Eclipse中的资源

来自分类Dev

在运行时创建Drawable并添加到资源中

来自分类Dev

Java Spring + Jersey子资源:在运行时注入Constructor-arg

来自分类Dev

QT ; 如何在运行时将资源路径存储到变量?

来自分类Dev

在运行时将半透明覆盖层添加到活动背景

Related 相关文章

热门标签

归档