android – Is this the correct way to have different values/styles for different versions-ThrowExceptions

Exception or error:
Android Studio 2.1 preview 3

This is just a question, as I am confused as I have seen many alternatives in doing this.

I have created a new android project and my Activity extends AppCompatActivity

public class MainActivity extends AppCompatActivity {

I want to have the transparent statusbar on devices running 21 and over.

So in my values/styles I have the following

<resources>
    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>
</resources>

And in my values-21/styles I have the following

<resources>
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>

        <!-- Make the statusbar transparent -->
        <item name="android:windowTranslucentStatus">true</item>
    </style>
</resources>

My Manifest I select the theme

android:theme="@style/AppTheme"

Just some questions

  1. Is this the correct way, or is there any better way to do this?
  2. Would values-21/styles inherit all the colors in values/styles so I would have to repeat this?
How to solve:

It’s the right way. May I suggest you to organize your style better?

values/styles.xml

<resources>
    <!-- Base application theme. -->
    <style name="AppTheme" parent="CommonTheme">

    </style>

    <style name="CommonTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>
</resources>

values-v21/styles.xml

<resources>
    <!-- Base application theme. -->
    <style name="AppTheme" parent="CommonTheme">
        <!-- All customization of the theme for this version -->
        <item name="android:windowTranslucentStatus">true</item>
    </style>
</resources>

So you don’t need to repeat the common values of the style for every api level.

###

I will try to answer it giving some references

Maintaining Compatibility

To avoid duplication of code, define your styles inside res/values/,
modify the styles in res/values-v21/ for the new APIs, and use style
inheritance, defining base styles in res/values/ and inheriting from
those in res/values-v21/

So you should try to avoid code duplication in your style.xml at different folders res/values/ and res/values-v21/ by using style inheritance.

Style Inheritence

If you want to inherit from styles that you’ve defined yourself, you
do not have to use the parent attribute. Instead, just prefix the name
of the style you want to inherit to the name of your new style,
separated by a period.

If you want to inherit a style that you’ve defined yourself you can skip adding a parent attribute and inherit from it using a dot or period notation.

With this, you can define a base theme BaseTheme in res/values/ with different colors and inherit from it as BaseTheme.StyledStatusBar without specifying a parent attribute.

<resources>
    <style name="BaseTheme.StyledStatusBar"></style>

    <!-- Base application theme. -->
    <style name="BaseTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>
</resources>

In values-21/, add item android:windowTranslucentStatus to BaseTheme.StyledStatusBar

<resources>
    <style name="BaseTheme.StyledStatusBar">
        <item name="android:windowTranslucentStatus">true</item>
    </style>
</resources>

In manifest, select the theme

android:theme="@style/BaseTheme.StyledStatusBar"

###

1) Is this the correct way, or is there any better way to do this?

Yes. That’s the correct/recommended way of having different values for different API versions.

2) Would values21/styles inherit all the colors in values/styles so I would have to repeat this?

I’m not sure I fully follow this question. Both styles you showed will inherit from Theme.AppCompat.Light.NoActionBar so your colors should be declared again, but I’ll present two better alternatives:

Alternative 1, a little bit better:

Use a BaseTheme that is common for both. To view the code for it, please check @mimmo-grottoli answer.

Alternative 2, much better:

If the only different on the two themes is the android:windowTranslucentStatus that was introduced in KitKat (API level 19), you can put it all in the same theme in values/styles, like the following:

<resources>
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>

        <!-- Make the statusbar transparent -->
        <item name="android:windowTranslucentStatus">true</item>
    </style>
</resources>

The Android Framework ignores XML parameters that it does not recognize. That means that on JellyBean or ICS, the device will ignore windowTranslucentStatus while correctly applying the colors and in KitKat and up, it will correctly apply windowTranslucentStatus.

That tricky is valid for all XML in Android (even layouts), the IDE might give you warnings about API level, but in XML they’re always safe to use.

###

Different folders of values/styles are made to give a unique style when your app is running on a specific version of Android.

So yes you are right when saying that the newer version inherits from the older one. When adding items in your latest version of styles you keep the latest version up to date to the latest APIs.

To conclude, your way is the very commun way, it’s an organized and a clean way to keep your app updated.

###

  1. Is this the correct way, or is there any better way to do this?

Yes. That’s the right way of having different values for different API versions.

Would values-21/styles inherit all the colors in values/styles so I would have to repeat this?

Yes

###

technically <item name="android:windowTranslucentStatus">true</item> won’t give you fully transparent statusbar.

If you want it to by fully transparent, you can use <item name="android:statusBarColor">@android:color/transparent</item>

Leave a Reply

Your email address will not be published. Required fields are marked *