2017-01-26 35 views
7

我知道有在styles.xml定义设置主题和使用它像如何从android中的另一个应用程序资源更改主题?

setTheme(android.R.style.MyTheme); 

不过,我想从另一个应用程序,我开发以及获得主题的方式。我知道资源名称,实际上我能够使用此代码块获取主题ID;

Resources res = getPackageManager().getResourcesForApplication("com.example.theme"); 
int resThemeId = res.getIdentifier("my_theme","style","com.example.theme"); 

当我调试时,我看到resThemeId不是零。

然后,我需要最后的命令来设置这个主题。 super.onCreate()函数之前,我尝试实施这种方法,但现在看来,这是行不通的

setTheme(resThemeId); 

但不是这个,如果我写下面的语句,我工作得很好

setTheme(android.R.style.Theme_Holo_Light); 

所以,我该怎么做才能使用来自不同包资源的主题?

+3

您可以从另一个软件包获取资源ID,但这些资源在您的APK中不存在。使用'PackageManager#getResourcesForApplication(String packageName)'加载资源应该适用于drawables,strings,bools等。但是,我不相信这是可能的,绝对不推荐加载其他APK的主题。 –

+0

虽然我可以从其他软件包资源中获取绘图,字符串,布尔值,但我希望获得主题。为什么不可能? – Berkay92

+0

这是可能的(见我的答案)。您需要重写getResrouces以返回其他应用程序的资源,以便可以应用该主题。这也将返回来自其他应用程序的所有字符串,布局,绘图和其他资源,因此,不建议这样做。 –

回答

3

那么,我应该怎么做才能使用不同包装资源的主题?

您不应该这样做,原因很多。我写了一个简单的项目,表明只要包中包含您的活动使用的资源,就可以实现。

请参见:https://github.com/jaredrummler/SO-41872033


基本上,你需要从活动返回程序包的资源:

public class MainActivity extends AppCompatActivity { 

    Resources resources; 

    @Override protected void onCreate(Bundle savedInstanceState) { 

    int themeResId = getResources().getIdentifier("AppTheme", "style", "com.example.theme"); 
    if (themeResId != 0) { 
     setTheme(themeResId); 
    } 

    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    } 

    @Override public Resources getResources() { 
    if (resources == null) { 
     try { 
     resources = getPackageManager().getResourcesForApplication("com.example.theme"); 
     } catch (PackageManager.NameNotFoundException e) { 
     resources = super.getResources(); 
     } 
    } 
    return resources; 
    } 

} 

这只是表明它是可能的。同样,我建议你避免这种情况。

+0

这样可以在运行时更改资源吗?我的意思是,我想从其他资源设置主题后设置原始资源? – Berkay92

+0

我不认为这是可能的,但我也不认为从其他软件包应用主题是可能的。这就是为什么我不会推荐这个解决方案。您不希望将其他包的资源用于布局和活动中的任何可绘制对象。你试图用这个来达到什么目的? –

+0

我其实尝试写一个主题管理器和不同的apk包含一些主题(主题包括背景图像,默认声音,应用程序图标等)。当我打开主题管理器应用程序时,我可以检索drawable并从主题apk中相应地列出它们。不过,我还想在更改主题时更改一些应用程序主题(如“设置”应用程序)。 (我想设置主要颜色等)顺便说一下,我正在开发AOSP项目,并且可以轻松更改设置代码。我只想从我的一个主题应用程序资源中更改设置主题。 – Berkay92

4

正如评论中已经提到的那样,您可以从其他应用程序访问资源,但使用其他应用程序主题将不起作用。


由于具有证明始终是一件好事,让我们来看看源代码(我用API 24个源)

Activity调用setTheme()将调用initializeTheme()ContextThemeWrapper父类,这将最终调用onApplyThemeResource(..)这反过来将尝试通过调用theme.applyStyle(resId, true)

继通过包装Resources.Theme链,我们可以在ResourcesImpl.ThemeImpl看到以下加载从资源的实际主题数据w这里AssetManager叫的风格装入主题:

void applyStyle(int resId, boolean force) { 
    synchronized (mKey) { 
     AssetManager.applyThemeStyle(mTheme, resId, force); 

     mThemeResId = resId; 
     mKey.append(resId, force); 
    } 
} 

这是你尝试,并无法从您的其他应用程序加载国外主题。


由于大多数的方法,您将需要使用的都是静态的电话或封装本地方法似乎不存在任何方式来实现你想要的,(如应用或创建一个新的主题)

即使您通过在上下文there is no accessible method to create or apply themes上使用getAssets()获得其他应用程序的AssetManager的保留。

因此,使用其他应用资源的唯一方法是将资源添加到您的资源。

+0

sharedUserId怎么样?如果我将sharedUserId用于应用程序并使用相同的证书签名,会发生什么情况?我试过但没有运气。也许我在代码的某个地方做错了 – Berkay92

1

你见过这个演示:Multiple Theme Material Design

您可以检查此演示了运行时的主题变化。

希望它能帮助你。

+0

要求更改设备上安装的其他软件包的主题。这会将应用程序主题更改为当前包的样式中预定义的主题。虽然这是应用主题的推荐方式,但它并不回答OP的问题。 –

相关问题