如何以编程方式创建Android主题样式?

时间:2015-09-26 12:55:41

标签: android android-styles

有许多关于通过XML创建或自定义Android主题样式的文档和教程,但未能找到在代码中创建它的方法。关于如何在代码而不是xml中创建样式的任何想法?

这是示例XML,需要在代码中以编程方式创建:

<resources>
  <style name="AppTheme" parent="android:Theme.Material">
    <item name="android:colorPrimary">@color/primary</item>
    <item name="android:colorPrimaryDark">@color/primary_dark</item>
    <item name="android:colorAccent">@color/accent</item>
  </style>
</resources>

2 个答案:

答案 0 :(得分:3)

简短回答:以编程方式不可能  创造一个主题&amp;设置为应用程序主题(即使我们实现了创建Theme对象)没有主题资源ID。

详细信息:

当您致电setTheme时,该功能会影响ContextWrapper的方法,  最后用资源id指针调用AssetManagerAssetManager类保存应用程序主题的方法,即JNI调用

native static final void applyThemeStyle(long theme, int res, boolean force);

如上所述,我们只能传递资源ID来应用themestyle。但可能的选择是

  1. 虽然它仅限于Window类特征常量。我们可以用 setFeatureDrawable&amp;用于设置一些drawable的特征常量 比如FEATURE_ACTION_BARFEATURE_CONTEXT_MENU等..
  2. 使用活动中的setTheme功能,我们可以从样式资源中设置主题,这将解决AjaySharma&amp;的评论中提到的问题。 Nathan

答案 1 :(得分:2)

TL; DR:不,您不能。这就是Android的工作方式,而且永远不会改变。


有一个简单明了的原因,使得无法以编程方式创建Android主题。也就是说,启动应用程序时,Android将创建一个虚拟窗口,其中显示了应用程序的android:windowBackground。此时,应用程序进程仍在初始化,并且当应用程序执行开始并返回所启动活动的Activity.onCreate方法时,虚拟窗口将替换为显示该活动的应用程序窗口。
因此,事实是,由于android:windowBackground是由主题设置的,但是Android甚至必须在应用启动之前就访问它,因此主题必须是资源,以便可以从以下任何进程(包括系统进程)访问它们:课程。)

此外,主题是资源,因此它们是完全不变的。这就是Android的工作方式。它不能只是突然改变,而且很可能永远不会改变。资源永远无法动态修改的另一个原因是直接的暗示,即APK本身也需要修改-这也不是APK的意思。

有人可能会争辩说“一切都必须以编程的方式在后台进行。”好吧,这是正确的。但是,android.content.res.Resources.Theme类之所以是最终类是有原因的,这是为了确保什么都不会被覆盖,因此可以保证其行为能够反映资源的内容,这对于系统进程访问{{1}活动主题的}与应用程序启动后的行为方式保持一致。对于android:windowBackground方法也是如此,这也是最终的方法。确实,如果应用程序可以覆盖该方法,它将能够返回与资源不匹配的值,这是一个问题,因为只有当应用程序启动后,原始的真实android.content.Context.obtainStyledResources才会发生已经显示。