【问题标题】:Changing themes and styles based on the Android version on build在构建时根据 Android 版本更改主题和样式
【发布时间】:2015-06-25 12:23:42
【问题描述】:

我知道我可以为不同的 API 级别添加不同的 XML,例如为 values-v21 和 values-v19 提供不同的样式。我想了解的是构建系统实际上如何使用这些不同的值?因此,例如,如果我的大部分样式在所有 API 中都是通用的,并且一种样式中的一项在 21 和其余之间发生变化,我会:

1) 将整个styles.xml 复制到v21 并更改我需要更改的一个值

2) 只添加 v21 下更改为 styles.xml 的那一种样式

3) 只添加21岁以下改变的那一种风格的那一项

这很令人困惑,我找不到任何文档,构建过程如何处理合并样式。

【问题讨论】:

    标签: android android-styles


    【解决方案1】:

    规则很明确:

    1. 运行安卓时selects the best-matching style
    2. 如果所选样式是子样式,Android merges 其与父样式最匹配的项目

      如果您通过引用提供可变项,只需定义其值以匹配所选 api 版本。

      <style name="SomeStyle">
          <item name="someColor">@color/some_color</item>
      </style>
      

    对于 API 21,您可以在 color-v21 文件夹中拥有 some_color.xml,对于所有其他 API 级别,您可以在 color 文件夹中拥有此文件的通用版本。

    示例:

    您希望非 v21 API 具有以下样式

        <style name="FinalStyle">
            <item name="commonText">It\'s a common text</item>
            <item name="specificDrawable">@drawable/icon</item>
            <item name="specificColor">@color/primary_color</item>
            <item name="specificText">non-v21</item>
        </style>
    

    以及 v21 API 的以下样式

        <style name="FinalStyle">
            <item name="commonText">It\'s a common text</item>
            <item name="specificDrawable">@drawable/icon</item>
            <item name="specificColor">@color/secondary_color</item>
            <item name="specificText">v21</item>
        </style>
    

    v21/non-v21 API 的具体参数不同,通用参数是通用的。

    怎么做?

    • res/values/styles.xml

      <style name="BaseStyle">
          <item name="commonText">It\'s a common text</item>
          <item name="specificDrawable">@drawable/icon</item>
      </style>
      
      <style name="FinalStyle" parent="BaseStyle">
          <item name="specificColor">@color/primary_color</item>
          <item name="specificText">non-v21</item>
      </style>
      
    • res/values-v21/styles.xml

      <style name="FinalStyle" parent="BaseStyle">
          <item name="specificColor">@color/secondary_color</item>
          <item name="specificText">v21</item>
      </style>
      
    • res/drawable/icon.png 常用图标

    • res/drawable-v21/icon.png v21 图标

    当 Android 在 FinalStyle 中搜索 v21 时,它会从 res/values-v21 中选择 FinalStyle 定义作为最佳匹配样式,并与 BaseStyle 合并。在此示例中,还有另一个最佳匹配资源搜索,即 Android 搜索 @drawable/icon

    【讨论】:

    • 所以基本上如果我在 v21 和普通版本中有两种样式,每个样式有 10 个项目,并且 1 个项目应该不同,我需要在 v21 下复制整个样式?
    • 如果我的第一个样式有父样式,我需要复制那个样式和它的父样式,即不能在样式的版本之间继承?
    • 您不能在样式的版本之间继承,但您可以提取通用的基本样式,然后为通用和 v21 版本创建子样式。
    • 一个例子将不胜感激 :) 我正在处理很多应用程序风格,所以复制粘贴所有风格的所有版本的所有风格只是地狱
    【解决方案2】:

    您只能为所有设备版本维护一个 styles.xml(默认)文件。

    查看我对How to remove repeating of similar styles in v19/styles.xml and v21/styles.xml files 的回答 https://stackoverflow.com/a/53445541/5745574

    【讨论】:

      【解决方案3】:

      这适用于任何遇到此问题并且仍然像我一样困惑的人,即使经过大量阅读和反复试验。希望这会有所帮助。

      文件夹结构如@Dmitry 所述。

      res/values/styles.xml

      <?xml version="1.0" encoding="utf-8"?>
      <resources xmlns:tools="http://schemas.android.com/tools">
      
          <style name="AppBase" parent="Theme.MaterialComponents.NoActionBar">
              <!-- simple: overrides colorPrimary in parent theme -->
              <item name="colorPrimary">@color/brand_blue</item>
              <item name="colorSecondary">@color/brand_grey</item>
              <!-- sets the attributes in materialButtonStyle with style: myMaterialButton -->
              <!-- the materialButtonStyle attribute is what actually changes the button settings -->
              <item name="materialButtonStyle">@style/myMaterialButton</item>
          </style>
      
          <!-- this style consists of common 'attributes' among all API versions -->
          <!-- you can choose to add a parent to inherit an additional style -->
          <!-- unlike the materialButtonStyle attribute, this parent is not necessary to change the button settings -->
          <style name="myMaterialButton" parent="Widget.MaterialComponents.Button">
              <item name="cornerRadius">60dp</item>
              <item name="android:paddingVertical" tools:targetApi="26">20dp</item>
          </style>
      
          <!-- this will add on and override AppBase and should include any changes that differ from other API versions -->
          <style name="AppBaseChanges" parent="AppBase">
              <!-- to inherit myMaterialButton, you don't have to include it in here, since it's in AppBase -->
              <!-- however, if you want to extend myMaterialButton, create a new style as its child -->
              <item name="materialButtonStyle">@style/myMaterialButtonAPI_All</item>
          </style>
      
          <!-- make sure the parent is myMaterialButton to inherit/override its settings -->
          <!-- this will be picked for all APIs lower than other styles like this -->
          <style name="myMaterialButtonAPI_All" parent="myMaterialButton">
              <item name="backgroundTint">?attr/colorPrimary</item>
          </style>
      </resources>
      

      res/values-v2/styles.xml

      <?xml version="1.0" encoding="utf-8"?>
      <resources>
      
          <!-- restate the same declaration as the other xml file-->
          <style name="AppBaseChanges" parent="AppBase">
              <!-- use a different name (...API_2) for the overriding style -->
              <item name="materialButtonStyle">@style/myMaterialButtonAPI_2</item>
          </style>
      
          <style name="myMaterialButtonAPI_2" parent="myMaterialButton">
              <item name="backgroundTint">?attr/colorSecondary</item>
          </style>
      </resources>
      

      将清单主题设置为AppBaseChanges。该应用只会选择一种AppBaseChanges 样式来应用更改,因此请务必小心地覆盖正确的样式,以确保您继承自较低级别的版本。

      由于某种原因,AndroidStudio 不能很好地预览主题,所以在您认为它不起作用之前,请重新启动应用程序以查看更改。在某些情况下,我不知道为什么它没有更新设置并且找不到它覆盖主题的位置。在这些情况下,您可以进一步挖掘,或者避免麻烦,直接将相关样式应用于视图。

      这是上述示例主题的优先顺序。样式越高,它的优先级就越高,并且会覆盖较低的样式。

      1. myMaterialButtonAPI_AllmyMaterialButtonAPI_2
      2. AppBaseChanges(只选一个)
      3. myMaterialButton
      4. Widget.MaterialComponents.Button
      5. AppBase
      6. Theme.MaterialComponents.NoActionBar

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-09-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-06-06
        相关资源
        最近更新 更多