如何在应用中使用设备默认主题?

43

我有一个想要开发的应用程序,要在 Android 2.1、2.2、2.3.3、3.0/3.1 和 4.0.x 上使用。在这些 API 级别之间,大约有三种不同类型的主题。最新的 4.0.x 主题是 Holo。

不管设备是什么,我希望我的应用程序都使用默认的 Android 主题。如果它在 4.0.x 设备上,我希望它使用 Holo 主题。如果它在 2.3.3 设备上,我希望它使用那个版本的 Android 主题等等...

是否有简单的方法来实现这一点?我注意到,在 4.0 版本中,他们添加了一个 Theme.DeviceDefault 主题,但这对于旧的 API 级别没有帮助。什么是最好的方法?

2个回答

73

当前Android设备上最多有3个(有时4个)主题可用(不包括.Light变体及类似内容)。

Theme

Theme

是早期版本的Android默认主题,从2.3 Gingerbread(10)开始使用。这些版本中可能有一些次要的样式更改。


Theme.Holo

Theme.Holo

在Android 3.0 Honeycomb(11)中引入。


Theme.Material

Theme.Material

在Android 5.0 Lollipop(21)中首次出现。


Theme.DeviceDefault

(可能是任何东西)

在Android 4.0 Ice Cream Sandwich (14)中引入,该主题可以由设备制造商进行自定义。它代表了设备的本机外观——例如,在Nexus设备及Android Studio设计编辑器中是Holo或Material,其他设备可能是一些自定义主题。如果“自定义主题”不是一个选项,则这些设备必须配备原始主题。想要使用原始主题的应用程序必须进行指定。


这个问题的最佳解决方案是什么?

没有主题 + targetSdkVersion >= 14

最简单但未必是最好的方法是根本不定义主题。Android将为您选择默认值。但是,Android不希望意外地给您的应用程序提供意料之外的主题,因此它会回退到您可能为其设计的主题。为此,它查看AndroidManifest.xml中的android:targetSdkVersion(现在可以通过gradle设置)。

  • 目标平台是旧版本(只有Theme,即API级别3-10),则只得到Theme
  • 针对11-13的应用程序将得到Theme.Holo
  • 14或以上版本将获得Theme.DeviceDefault

由于这只是为了向后兼容,因此您不会在旧版Gingerbread手机上获得Theme.Material。因此,无主题+目标14+=设备默认值。

指定不同的主题

Android的资源叠加系统允许基于设备API级别指定样式。例如,在res/values-v11res/values-v21中有不同版本的样式。这也是通过Android Studio新创建的任何应用程序为您设置的方式。

例如,一个.Light主题的基本设置如下:

/res/values/styles.xml适用于每个设备并作为基础。

<resources>
    <style name="AppTheme" parent="android:Theme.Light"/>
</resources>

/res/values-v11/styles.xml 文件在 API 等级为 11 及以上的所有设备上加载(包括版本号为 21及以上的设备)。但只有最新版本的“AppTheme”实际被使用。


<resources>
    <style name="AppTheme" parent="android:Theme.Holo.Light"/>
</resources>

/res/values-v21/styles.xml

<resources>
    <style name="AppTheme" parent="android:Theme.Material.Light"/>
</resources>

注意:在/res/values-v14/styles.xml中替代指定Theme.DeviceDefault应该足以拥有默认的外观,但这不允许微调设计。添加v14覆盖不会有害。毕竟,DeviceDefault和Holo可能是不同的。


AndroidManifest.xml是使用自定义主题的地方。例如作为全局应用程序默认主题:

...
<application
    android:theme="@style/AppTheme"
    ...

官方文档链接

根据平台版本选择主题 - 此官方文档介绍通过资源配置定义不同样式的方法。

Holo Everywhere - 博客文章,解释了默认机制和DeviceDefault / Holo主题。

使用材料主题 - 材料文档。


我需要对此进行一些实验。如果我将 targetSdkVersion="11",那么它会如何影响在 2.1、2.2 和 2.3.3(API 级别 7、8 和 9/10)上运行我的应用程序的设备?我想我有点困惑于目标 API 级别和最低 API 级别之间的区别。 - Jake Wilson
targetSdkVersion 表示兼容某个 API 级别。如果您的应用在更高级别的设备上运行,则启用一些兼容选项,并使设备行为像您指定的最高级别。如果设备低于您的目标级别,则它仅表现得像它本来那样。最小级别是您的应用程序需要运行的级别-下面的设备无法工作。因此,您必须确保所有最小和目标级别之间的设备都能正常工作。 - zapl
1
关于想要以平台相关的方式使用.Light主题,您可以尝试使用Theme.DeviceDefault.Light - Sam

3
您可以在values/styles.xml中声明一个主题,然后在values-v11/styles.xml中使用Holo版本覆盖它:
values/styles.xml:
 <style name="DialogTheme" parent="@android:style/Theme.Dialog"></style>

values-v11/styles.xml:

 <style name="DialogTheme" parent="@android:style/Theme.Holo.Light.Dialog.NoActionBar"></style>

按照这种方式操作,您的API 11+设备将拥有Holo主题,其他设备则为常规主题。

祝好 Steffen Vangsgaard


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接