how to access custom attribute with multiple forma

2019-04-29 17:10发布

问题:

I read in another answer that in android you can declare attributes for your custom view that have multiple formats like this:

<attr name="textColor" format="reference|color"/>

how can I access these attributes in my class? Should I just assume it to be a reference, use getResources().getColorStateList() and then assume it to be a raw RGB/ARGB color if Resources.getColorStateList() throws Resources.NotFoundException or is there a better way of differentiating between the formats/types?

回答1:

It should be something like this:

Variant 1

public MyCustomView(Context context,
                    AttributeSet attrs,
                    int defStyleAttr,
                    int defStyleRes) {
    super(context, attrs, defStyleAttr, defStyleRes);
    TypedArray typed = context.obtainStyledAttributes(attrs, R.styleable.MyCustomView, defStyleAttr, defStyleRes);
    int resId = typed.getResourceId(R.styleable.MyCustomView_custom_attr, R.drawable.default_resourceId_could_be_color);
    Drawable drawable = getMultiColourAttr(getContext(), typed, R.styleable.MyCustomView_custom_attr, resId);
    // ...
    Button mView = new Button(getContext());
    mView.setBackground(drawable);

}

protected static Drawable getMultiColourAttr(@NonNull Context context,
                                             @NonNull TypedArray typed,
                                             int index,
                                             int resId) {
    TypedValue colorValue = new TypedValue();
    typed.getValue(index, colorValue);

    if (colorValue.type == TypedValue.TYPE_REFERENCE) {
        return ContextCompat.getDrawable(context, resId);
    } else {
        // It must be a single color
        return new ColorDrawable(colorValue.data);
    }
}

Of course getMultiColourAttr() method could be not static and not protected, this is up to the project.

The idea is to get some resourceId for this specific custom attribute, and use it only if the resource is not color but TypedValue.TYPE_REFERENCE, which should means that there is Drawable to be obtained. Once you get some Drawable should be easy to use it like background for example:

mView.setBackground(drawable);

Variant 2

Looking Variant 1 you can use the same resId but just pass it to the View method setBackgroundResource(resId) and the method will just display whatever stays behind this resource - could be drawable or color.

I hope it will help. Thanks



回答2:

In your /res/attrs.xml:

<declare-styleable name="YourTheme">
    <attr name="textColor" format="reference|color"/>
</declare-styleable>

In your custom view constructor, try something like that (I didn't run it):

int defaultColor = 0xFFFFFF; // It may be anyone you want.
TypedArray attr = getTypedArray(context, attributeSet, R.styleable.YourTheme);
int textColor = attr.getColor(R.styleable.YourTheme_textColor, defaultColor);