Android:如何获取当前主题的资源ID?

时间:2011-09-01 08:35:06

标签: android

在Android中,您可以将活动的当前主题从Resource.Theme作为getTheme()对象获取。此外,您可以通过其他主题的资源ID将主题设置为不同的主题,如setTheme(R.style.Theme_MyTheme)

但我怎么知道它是否值得 - 目前的主题是否已经是我想要设定的主题?我正在寻找像getTheme().getResourceId()这样的东西,以便写出类似的东西:

protected void onResume() {
    int newThemeId = loadNewTheme();
    if (newThemeId != getTheme().getResourceId()) { // !!!! How to do this?
        setTheme(newThemeId);
        // and rebuild the gui, which is expensive
    }
}

有什么想法吗?

5 个答案:

答案 0 :(得分:41)

好的,这里有一个谜题:我们可以获得在AndroidManifest.xml中设置的默认主题,在应用程序级别设置主题context.getApplicationInfo().theme,从活动中获取,作为该活动的getPackageManager().getActivityInfo(getComponentName(), 0).theme

我想这给了我们一个起点,让我们为自定义getTheme()setTheme()做自己的包装。

仍然感觉就像围绕而不是使用 API。所以我会把问题留下来看看是否有人提出了更好的想法。

编辑:

getPackageManager().getActivityInfo(getComponentName(), 0).getThemeResource()

如果活动没有覆盖它,它将自动回退到应用程序主题。

答案 1 :(得分:37)

我找到了一种在不获取资源ID的情况下解决需求的方法。

我正在使用字符串的名称为我的每个主题添加一个项目:

<item name="themeName">dark</item>

在代码中我检查名称如下:

TypedValue outValue = new TypedValue();
getTheme().resolveAttribute(R.attr.themeName, outValue, true);
if ("dark".equals(outValue.string)) {
   ...
}

答案 2 :(得分:9)

有一种方法可以通过反射来做到这一点。把它放在你的活动中:

int themeResId = 0;
try {
    Class<?> clazz = ContextThemeWrapper.class;
    Method method = clazz.getMethod("getThemeResId");
    method.setAccessible(true);
    themeResId = (Integer) method.invoke(this);
} catch (NoSuchMethodException e) {
    Log.e(TAG, "Failed to get theme resource ID", e);
} catch (IllegalAccessException e) {
    Log.e(TAG, "Failed to get theme resource ID", e);
} catch (IllegalArgumentException e) {
    Log.e(TAG, "Failed to get theme resource ID", e);
} catch (InvocationTargetException e) {
    Log.e(TAG, "Failed to get theme resource ID", e);
}
// use themeResId ...

[在此处插入关于非公开apis的免责声明]

答案 3 :(得分:6)

根据sources Activity.setTheme在Activity.onCreate之前调用,所以你可以在android设置时保存themeId:

public class MainActivity extends Activity {
    private int themeId;

    @Override
    public void setTheme(int themeId) {
        super.setTheme(themeId);
        this.themeId = themeId;
    }

    public int getThemeId() {
        return themeId;
    }
}

答案 4 :(得分:0)

如果您在清单中的android:theme="@style/SomeTheme"元素中指定了<activity/>,那么您可以像下面这样获得活动主题的资源ID:

int themeResId;
try {
    PackageManager packageManager = getPackageManager();
    //ActivityInfo activityInfo = packageManager.getActivityInfo(getCallingActivity(), PackageManager.GET_META_DATA);
    ActivityInfo activityInfo = packageManager.getActivityInfo(getComponentName(), PackageManager.GET_META_DATA);
    themeResId = activityInfo.theme;
}
catch(PackageManager.NameNotFoundException e) {
    Log.e(LOG_TAG, "Could not get themeResId for activity", e);
    themeResId = -1;
}

别忘了,如果您要在活动的 onCreate()方法中调用setTheme(themeResId),则需要在调用前 setContentView(...)