实现主题的用户select

我想给用户在几个不同的主题之间进行select,并且想知道这是不是一种正确的做事方式。 我用这个方法做了一些testing,结果很有效果,但是我觉得可能有更好的方法,以为以后可能会导致一些问题,所以想问一下。

我正在考虑为每个主题创build一个不同的布局,并在onCreate只是有一个开关setContentView()方法。 我会首先加载一个保存的SharedPreference值(整数),并根据该值显示相应的布局。 很显然,用户可以用一个button或者其他的东西来改变SharedPreference值。

由于这些布局基本上是相同的,但颜色不同,所以我想为每个布局文件中的TextViews和其他视图使用相同的ID。 我的主要问题是这会造成问题吗?

对不起,没有代码的文字墙。 我只想为这种情况得到一个好的实践的总体思路。 提前致谢。

我实际上在我的应用程序中有这个function,另外,我允许用户在运行时更改主题。 由于从喜好中读取值需要一些时间,我通过全局可访问的函数获取主题ID,该函数保存caching的值。

正如已经指出的那样 – 使用本指南创build一些Android主题。 您的styles.xml文件中至less有两个<style>项目。 例如:

 <style name="Theme.App.Light" parent="@style/Theme.Light">...</style> <style name="Theme.App.Dark" parent="@style/Theme">...</style> 

现在,您必须将其中一种样式应用于您的活动。 我在活动的onCreate方法,在任何其他调用之前,这样做:

 setTheme(MyApplication.getThemeId()); 

getThemeId是返回caching的主题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是一个布尔variables,最初设置为false。 当此侦听器更改主题时,它被设置为true,并更新之前提到的caching的主题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); 

记住要保持对监听器对象的引用,否则它将被垃圾收集(并且将停止工作)。

您也可以使用以下dynamic更改主题:

 ContextThemeWrapper w = new ContextThemeWrapper(this, <newTHEMEId>); getTheme().setTo(w.getTheme()); 

在创build每个活动之前。

如果你这样做的话,它确实有效,我不认为这会造成任何问题,但是看起来很麻烦(你必须把所有你想要添加的主题的所有布局放在一起。想要修改布局中的资源,必须在所有主题中进行修改,你一定会忘记一个)

为什么不使用Android的样式和主题function?

他们可以很容易地应用到整个活动中:

 <activity android:theme="@style/my_theme"> 

因此,当您检测到您使用的SharedPreferences值的变化时(您可以在首选项活动上button),只需切换样式即可。 或者更好的是,你可以设置风格在运行时(创build活动时)读取你的首选项值,并相应地应用正确的风格/主题。