实现用户选择主题
我想让用户在几个不同的主题之间进行选择,并且想知道这是否是一种好的做事方式。我用这个方法做了一点测试,它有效,但我认为可能有更好的方法,并且认为它可能会在以后引起一些问题,所以想问一下。
我正在考虑为每个主题创建不同的布局,并在 onCreate
中为 setContentView()
方法设置一个开关。我首先加载保存的 SharedPreference 值(整数),然后根据该值显示相应的布局。显然,用户可以使用按钮或其他东西更改 SharedPreference 值。
由于这些布局基本相同但颜色不同,因此我希望对每个布局文件中的 TextViews
和其他视图使用相同的 ID。我的主要问题是这会引起问题吗?
抱歉,没有代码的文字墙。我只是想了解针对这种情况的良好实践的一般概念。提前致谢。
I want to give the user the choice between a few different themes, and was wondering if this is an alright way of doing things. I did a little test with this method and it worked, but I think there may be better ways and think it may cause some problems later on, so wanted to ask.
I was thinking of creating a different layout for each theme, and in onCreate
just having a switch for the setContentView()
method. I'd load a saved SharedPreference
value (integer) first and depending on what that value was display the corresponding layout. Obviously the user could change the SharedPreference
value with a button or something.
As these layouts would be basically the same but with different colours, I'd want to use the same IDs for my TextViews
and other Views in each layout file. My main question is would this cause problems?
Sorry for the wall of text with no code. I'd just like to get a general idea of good practice for this situation. Thanks in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
实际上,我的应用程序中有此功能,此外,我允许用户在运行时更改主题。由于从首选项中读取值需要一些时间,因此我通过保存缓存值的全局可访问函数获取主题 id。
正如已经指出的 - 使用本指南创建一些 Android 主题。
styles.xml
文件中至少有两个项。例如:
现在,您必须将这些样式之一应用到您的活动中。我在 activitie 的
onCreate
方法中执行此操作,然后再进行任何其他调用:getThemeId
是一个返回缓存主题 ID 的方法:此字段正在由另一个方法更新:
哪个是每当首选项发生更改时(当然,在启动时)都会被调用。这两个方法位于
MyApplication
类中,该类扩展了Application
。首选项更改侦听器在本文末尾进行了描述,并且位于主活动类中。最后也是非常重要的一件事 - 当活动开始时应用主题。假设您只能在首选项屏幕中更改主题,并且只有一种方法可以到达那里,即仅从一个(主要)活动,当您退出首选项屏幕时,该活动不会重新启动 - 旧主题仍然会是用过的。以下是解决该问题的方法(重新启动您的主要活动):
scheduledRestart 是一个布尔变量,最初设置为 false。当此侦听器更改主题时,它设置为 true,这也会更新之前提到的缓存主题 ID:
请记住保存对侦听器对象的引用,否则它将被垃圾收集(并且将停止工作)。
I actually have this feature in my application and additionally, I allow users to change theme at runtime. As reading a value from preferences takes some time, I'm getting a theme id via globally accessible function which holds cached value.
As already pointed out - create some Android themes, using this guide. You will have at least two
<style>
items in yourstyles.xml
file. For example:Now, you have to apply one of these styles to your activities. I'm doing this in activitie's
onCreate
method, before any other call:getThemeId
is a method which returns cached theme ID:This field is being updated by another method:
Which is being called whenever preferences are changed (and, on startup of course). These two methods reside in
MyApplication
class, which extendsApplication
. The preference change listener is described at the end of this post and resides in main activity class.The last and pretty important thing - theme is applied, when an activity starts. Assuming, you can change a theme only in preference screen and that there's only one way of getting there, i.e. from only one (main) activity, this activity won't be restarted when you will exit preference screen - the old theme still will be used. Here's the fix for that (restarts your main activity):
scheduledRestart
is a boolean variable, initially set to false. It's set to true when theme is changed by this listener, which also updates cached theme ID mentioned before:Remember to hold a reference to the listener object, otherwise it will be garbage colleted (and will cease to work).
如果您使用 Material Components 主题 并遵循浅色和深色主题指南,那么您可以通过 AppCompatDelegate 来完成。这些主题可以在运行时更改/应用,而无需重新启动应用程序。
If you are using Material Components themes and followed Light and Dark theme guidelines then you can do it from
AppCompatDelegate
. These themes can be changed/applied at run time without restarting your application.您还可以使用以下方法动态更改主题:
在每个活动的 onCreate 之前。
You can also change dynamically theme using:
Before onCreate for each activity.
如果你这样做,它确实有效,而且我认为这不会造成任何问题,但似乎很麻烦(你必须将所有布局乘以你想要添加的所有主题。如果以后你想要修改布局中的资源,您必须在所有主题中修改它,您肯定会忘记一个)
为什么不使用样式和主题 功能?
它们可以轻松应用于整个活动:
这样,当您检测到您使用的 SharedPreferences 值发生更改(首选项活动上的按钮或其他内容)时,您只需切换样式即可。或者更好的是,您可以设置样式以在运行时(创建活动时)读取您的首选项值,并相应地应用正确的样式/主题。
It does work if you do it this way, and I don't think it would cause any problem, but it seems like a lot of hassle (you have to multiply all your layouts by all the themes you want to add. If later you want to modify a resource in a layout, you'll have to modify it in all the themes. You're definitely bound to forget one)
Why not using the Styles and Themes feature of Android?
They can be applied to the whole activity easily:
So that when you detect a change in the
SharedPreferences
value you use (button on a preference activity, or something) you can just switch the style. Or better, you can set the style to read your preference value at runtime (when creating the activity) and apply the correct style/theme accordingly.