Android:如何动态刷新活动/设置主题

mai*_*cio 1 android themes android-layout

我正在尝试在我的应用程序上实现主题切换,我似乎无法刷新活动并设置它们主题而无需重新启动整个活动(aka finish()+ startActivity()).

我尝试使findViewById(android.R.id.content)无效,但它不会刷新活动.改变方向会改变主题,因为再次调用onCreate.

那么像TweetLanes这样的应用程序如何实现此功能而无需重新启动应用程序/活动?

谢谢

ajo*_*joz 6

相当简单.

假设您有一个名为的资源文件/res/values/app_themes.xml.在此xml文件中,您可以定义应用程序样式.让我们称之为它appGeneralTheme应该看起来或多或少像这样:

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="appGeneralTheme">
    <!- Ofc you would use meaningful names and a separate file for colours but it's not the point. Those could be even different drawables, different strings, any kind of value can be styled/themed-->
    <item name="foo">#FF0000</item>
    <item name="bar">#00FF00</item>
    <item name="baz">#0000FF</item>
</style>
</resources>
Run Code Online (Sandbox Code Playgroud)

现在让我们定义用户可以更改的特定主题.我们可以通过几种方式实现:

  • 在同一个app_themes.xml文件中
  • 所有在另一个文件中,如: pickables_themes.xml
  • 每个都在一个单独的文件中:qux_theme.xml, quux_theme.xml等等

为了简单起见,我们将所有内容保存在一个地方,因此app_themes.xml我们将添加修改后的主题:

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="appGeneralTheme">
    <item name="foo">#FF0000</item>
    <item name="bar">#00FF00</item>
    <item name="baz">#0000FF</item>
    <!-- other items -->
</style>

<style name="quxTheme" parent="@style/appGeneralTheme">
    <item name="foo">#FF00FF</item>
    <item name="bar">#00FFFF</item>
    <item name="baz">#FFFF00</item>
</style>
<style name="quuxTheme" parent="@style/appGeneralTheme">
    <item name="foo">#FF0099</item>
    <item name="bar">#00AAFF</item>
    <item name="baz">#FF1100</item>
</style>
</resources>
Run Code Online (Sandbox Code Playgroud)

为什么parent?也许我们的风格只需要修改一小部分内容?也许我们想要特定值的默认值?

那么如何申请呢?我们需要做几件事:

  1. 打电话给Context.getTheme().applyStyle(resId, force).在Context我们有一个很好的方法Context.getTheme()这个方法允许我们在Theme对象上应用特定的样式.的描述Theme.applyStyle(...)应该给你的可能性的想法:

将新属性值放入主题中.

  1. 无论好坏,您都应该为活动上下文和应用程序上下文执行此样式应用程序.

  2. 你不需要杀死活动,一个简单的Activity.recreate()就可以了.现在开始变得有趣了.

根据应用程序的设计方式,一切都可能会闪烁.现在我们有多种方法: - 多个活动 - 单个活动 - 多个片段 - 没有片段 - 等等

这对最终的事情有影响.我只能根据自己对单个活动+片段的经验告诉你,如果你有几个片段交易,你会Activity.recreate()像迪斯科一样做屏幕闪烁.

有一个解决方法(相当hack-ish).您不能重新创建整个活动,而只能FragmentTransaction.detach(Fragment).attach(Fragment).commit()在最顶层的可见片段上进行.其他不可见的碎片应该没问题.

为什么这很有用:

  • 你不需要有这些物品(如:foo,bar,baz)的风格,是儿童定义appGeneralTheme,你可以有与其他地方定义的任何样式(如果你套用样式将覆盖)
  • 您可以逐个应用交错项目的几种样式来实现某些功能(根据另一个逻辑隐藏或显示某些内容)

适用于一般意义上的主题(颜色)