Android checkbox style

Note: Using Android Support Library v22.1.0 and targeting API level 11 and up? Scroll down to the last update.


My application style is set to Theme.Holo which is dark and I would
like the check boxes on my list view to be of style Theme.Holo.Light.
I am not trying to create a custom style. The code below doesn’t seem
to work, nothing happens at all.

At first it may not be apparent why the system exhibits this behaviour, but when you actually look into the mechanics you can easily deduce it. Let me take you through it step by step.

First, let’s take a look what the Widget.Holo.Light.CompoundButton.CheckBox style defines. To make things more clear, I’ve also added the ‘regular’ (non-light) style definition.

<style name="Widget.Holo.Light.CompoundButton.CheckBox" parent="Widget.CompoundButton.CheckBox" />

<style name="Widget.Holo.CompoundButton.CheckBox" parent="Widget.CompoundButton.CheckBox" />

As you can see, both are empty declarations that simply wrap Widget.CompoundButton.CheckBox in a different name. So let’s look at that parent style.

<style name="Widget.CompoundButton.CheckBox">
    <item name="android:background">@android:drawable/btn_check_label_background</item>
    <item name="android:button">?android:attr/listChoiceIndicatorMultiple</item>
</style>

This style references both a background and button drawable. btn_check_label_background is simply a 9-patch and hence not very interesting with respect to this matter. However, ?android:attr/listChoiceIndicatorMultiple indicates that some attribute based on the current theme (this is important to realise) will determine the actual look of the CheckBox.

As listChoiceIndicatorMultiple is a theme attribute, you will find multiple declarations for it – one for each theme (or none if it gets inherited from a parent theme). This will look as follows (with other attributes omitted for clarity):

<style name="Theme">
    <item name="listChoiceIndicatorMultiple">@android:drawable/btn_check</item>
    ...
</style>

<style name="Theme.Holo">
    <item name="listChoiceIndicatorMultiple">@android:drawable/btn_check_holo_dark</item>
    ...
</style>

<style name="Theme.Holo.Light" parent="Theme.Light">
    <item name="listChoiceIndicatorMultiple">@android:drawable/btn_check_holo_light</item>
    ...
</style>

So this where the real magic happens: based on the theme’s listChoiceIndicatorMultiple attribute, the actual appearance of the CheckBox is determined. The phenomenon you’re seeing is now easily explained: since the appearance is theme-based (and not style-based, because that is merely an empty definition) and you’re inheriting from Theme.Holo, you will always get the CheckBox appearance matching the theme.

Now, if you want to change your CheckBox‘s appearance to the Holo.Light version, you will need to take a copy of those resources, add them to your local assets and use a custom style to apply them.

As for your second question:

Also can you set styles to individual widgets if you set a style to the application?

Absolutely, and they will override any activity- or application-set styles.

Is there any way to set a theme(style with images) to the checkbox
widget. (…) Is there anyway to use this selector: link?


Update:

Let me start with saying again that you’re not supposed to rely on Android’s internal resources. There’s a reason you can’t just access the internal namespace as you please.

However, a way to access system resources after all is by doing an id lookup by name. Consider the following code snippet:

int id = Resources.getSystem().getIdentifier("btn_check_holo_light", "drawable", "android");
((CheckBox) findViewById(R.id.checkbox)).setButtonDrawable(id);

The first line will actually return the resource id of the btn_check_holo_light drawable resource. Since we established earlier that this is the button selector that determines the look of the CheckBox, we can set it as ‘button drawable’ on the widget. The result is a CheckBox with the appearance of the Holo.Light version, no matter what theme/style you set on the application, activity or widget in xml. Since this sets only the button drawable, you will need to manually change other styling; e.g. with respect to the text appearance.

Below a screenshot showing the result. The top checkbox uses the method described above (I manually set the text colour to black in xml), while the second uses the default theme-based Holo styling (non-light, that is).

Screenshot showing the result


Update2:

With the introduction of Support Library v22.1.0, things have just gotten a lot easier! A quote from the release notes (my emphasis):

Lollipop added the ability to overwrite the theme at a view by view level by using the android:theme XML attribute – incredibly useful for things such as dark action bars on light activities. Now, AppCompat allows you to use android:theme for Toolbars (deprecating the app:theme used previously) and, even better, brings android:theme support to all views on API 11+ devices.

In other words: you can now apply a theme on a per-view basis, which makes solving the original problem a lot easier: just specify the theme you’d like to apply for the relevant view. I.e. in the context of the original question, compare the results of below:

<CheckBox
    ...
    android:theme="@android:style/Theme.Holo" />

<CheckBox
    ...
    android:theme="@android:style/Theme.Holo.Light" />

The first CheckBox is styled as if used in a dark theme, the second as if in a light theme, regardless of the actual theme set to your activity or application.

Of course you should no longer be using the Holo theme, but instead use Material.

Leave a Comment