在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
}
}
有什么想法吗?
答案 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(...)
。