实际上,我的应用程序中具有此功能,此外,我允许用户在运行时更改主题。由于从首选项中读取值需要一些时间,我通过保存缓存值的全局可访问函数获取主题 ID。
正如已经指出的 - 创建一些 Android 主题,使用本指南。您的文件中至少有两个<style>
项目styles.xml
。例如:
<style name="Theme.App.Light" parent="@style/Theme.Light">...</style>
<style name="Theme.App.Dark" parent="@style/Theme">...</style>
现在,您必须将其中一种样式应用于您的活动。onCreate
在进行任何其他调用之前,我正在使用活动的方法执行此操作:
setTheme(MyApplication.getThemeId());
getThemeId
是一个返回缓存主题 ID 的方法:
public static int getThemeId()
{
return themeId;
}
此字段正在通过另一种方法更新:
public static void reloadTheme()
{
themeSetting = PreferenceManager.getDefaultSharedPreferences(context).getString("defaultTheme", "0");
if(themeSetting.equals("0"))
themeId = R.style.Theme_Light;
else
themeId = R.style.Theme_Dark;
}
每当更改偏好时都会调用它(当然,在启动时)。这两个方法驻留在MyApplication
扩展类中Application
。偏好更改侦听器在本文末尾进行了描述,位于主活动类中。
最后也是非常重要的事情 - 主题是在活动开始时应用的。假设,您只能在首选项屏幕中更改主题,并且只有一种方法可以到达那里,即只有一个(主要)活动,当您退出首选项屏幕时,此活动不会重新启动 - 旧主题仍然是用过的。这是解决方法(重新启动您的主要活动):
@Override
protected void onResume() {
super.onResume();
if(schduledRestart)
{
schduledRestart = false;
Intent i = getBaseContext().getPackageManager().getLaunchIntentForPackage( getBaseContext().getPackageName() );
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
}
}
scheduledRestart
是一个布尔变量,最初设置为 false。当此侦听器更改主题时,它设置为 true,这也会更新前面提到的缓存主题 ID:
private class ThemeListener implements OnSharedPreferenceChangeListener{
@Override
public void onSharedPreferenceChanged(SharedPreferences spref, String key) {
if(key.equals("defaultTheme") && !spref.getString(key, "0").equals(MyApplication.getThemeSetting()))
{
MyApplication.reloadTheme();
schduledRestart = true;
}
}
sp = PreferenceManager.getDefaultSharedPreferences(this);
listener = new ThemeListener();
sp.registerOnSharedPreferenceChangeListener(listener);
请记住持有对侦听器对象的引用,否则它将被垃圾收集(并且将停止工作)。