Lay González
Lay González

Reputation: 2985

How to create a selector for a color in Android (like a Color State List, but for custom attrs)?

This is what I have and doesn't work as expected

// some_color.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:custom="http://schemas.android.com/apk/res/com.example">

    <item custom:greyShadow="true" android:color="@color/grey_shadow"/>
    <item custom:blueShadow="true" android:color="@color/blue_shadow"/> 

</selector>

"greyShadow" and "blueShadow" are my custom attributes.

How I tried to use it:

I wanted to use it (the color selector some_color.xml) in a view via a style like this:

layout:

// some_layout.xml
// the style text_input_style.xml sets a drawable as a background, that drawable uses color selector
<EditText
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    custom:blueShadow="true" <!-- this is the custom attribute -->
    style="@style/text_input_style" <!-- this is the style -->
/>

style:

// text_input_style.xml
<style name="text_input_style_blue">
    <item name="android:background">@drawable/some_drawable.xml</item>
</style>    

Drawable:

//some_drawable.xml (used by text_input_style.xml)
<item>
    <shape android:shape="rectangle" >
       <solid android:color="@color/some_color"/> <!-- here, the drawable uses the color selector --> 
    </shape>
</item>

Upvotes: 2

Views: 1592

Answers (1)

Karakuri
Karakuri

Reputation: 38605

There are a number of problems happening here.

First: none of the standard Views in Android (including EditText) will recognize or make use of custom attributes you defined. In your layout, the line custom:blueShadow="true" on an EditText is meaningless. You would have to subclass EditText, read the attributes yourself, and apply them.

Second: The attributes you defined are intended for drawable selectors, not for views, so it doesn't make sense (to me at least) to apply them to a view in the layout XML. Generally you would use such attributes by subclassing a View and implementing onCreateDrawableState(), then calling refreshDrawableState when any change to the internal state of the view warrants updating the drawable state.

public class CustomEditText extends EditText {
    private boolean blueShadow;
    private boolean greyShadow;

    /* constructors omitted */

    public void setBlueShadow(boolean b) {
        if (blueShadow != b) {
            blueShadow = b;
            refreshDrawableState();
        }
    }

    public void setGreyShadow(boolean b) {
        if (greyShadow != b) {
            greyShadow = b;
            refreshDrawableState();
        }
    }

    @Override
    protected int[] onCreateDrawableState(int extraSpace) {
        int[] baseState = super.onCreateDrawableState(extraSpace + 2);
        if (blueShadow) {
            mergeDrawableStates(baseState, new int[]{ R.attr.blueShadow });
        }
        if (greyShadow) {
            mergeDrawableStates(baseState, new int[]{ R.attr.greyShadow });
        }
    }
}

Here's a good guide on how custom drawable states work: Charles Harley - Custom drawable states in Android.

Upvotes: 2

Related Questions