I have a custom view in which i want to set the color of a textview.
I have
attrs.xml
<declare-styleable name="PropertyView">
<attr name="propertyTitle" format="string" localization="suggested" />
<attr name="showTitle" format="boolean" />
<attr name="propertyTextColor" format="color" />
<attr name="propertyTextSize" format="dimension" />
</declare-styleable>
I set it in the layout file
<com.something.views.PropertyView
android:id="@+id/dwf_rAwayTeamTimePenaltyInput"
style="@style/mw"
propertyview:propertyTextSize="16sp"
propertyview:propertyTitle="@string/AwayTeam"
propertyview:showTitle="true"
propertyview:propertyTextColor="@color/textLight" />
And in my code I set it
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.PropertyView, 0, 0);
showTitle = a.getBoolean(R.styleable.PropertyView_showTitle, false);
String title = a.getString(R.styleable.PropertyView_propertyTitle);
float textSize = a.getDimension(R.styleable.PropertyView_propertyTextSize, -1);
int color = a.getColor(R.styleable.PropertyView_propertyTextColor, -1);
textSize = textSize / getResources().getDisplayMetrics().scaledDensity;
if(BuildConfig.DEBUG) Log.e(getClass().getName(), "Color set to: " + color);
setShowTitle(showTitle);
setTitle(title);
if(textSize >= 0) mTitleTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, textSize);
if(color != -1) mTitleTextView.setTextColor(color);
a.recycle();
But color keeps returning -1.
I also tried to set color to #000
When i do that i get a value of -16777216
I also tried a.getInteger and a.getInt
Anyone experience with this problem or suggestions?
Solution, thanks to Alex Fu
getColor cannot handle references
It is working now with
ColorStateList color = a.getColorStateList(R.styleable.PropertyView_propertyTextColor);
mTitleTextView.setTextColor(color);
You are using a reference to a color in your example, however according to your attrs.xml file, that property must be of a color type, not a reference. This is probably the reason why when you used a hex color code it worked, but using a reference returned -1.
If you do change the format to a reference, you should also change the method to retrieve it from a.getColor()
to a.getColorStateList()
.
The is some sort of bug with attrs
.
The following works perfectly.
attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Your View -->
<declare-styleable name="YourView">
<attr name="tint_color" format="reference" /> <!-- Important -->
<attr name="ripple_drawable" format="reference" /> <!-- Important -->
</declare-styleable>
</resources>
YourView.java
public YourView(Context context) {
this(context, null);
}
public YourView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public YourView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
// Get attrs
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.YourView, defStyleAttr, 0);
// Set tint
int tintStyle = R.styleable.YourView_tint_color;
if (a.hasValue(tintStyle)) {
mTintColor = a.getResourceId(tintStyle, 0); // Important
setTint(mTintColor);
}
// Set Ripple
int rippleStyle = R.styleable.YourView_ripple_drawable;
if (a.hasValue(rippleStyle)) {
mRippleDrawable = a.getResourceId(rippleStyle, 0); // Important
setRipple(mRippleDrawable);
}
// End
a.recycle();
}
Usage
<com.your.app.YourView
...
app:ripple_drawable="@drawable/ripple_default"
app:tint_color="@color/colorWhite" />
If you want every types of color to work
- hex:
#ff0000
- color resource:
@color/primary
- color selector:
@color/primaryWithStates
You need to define your property as both color and reference
<attr name="propertyTextColor" format="color|reference" />
Then you simply access the value using getColorStateList
val colors = attr.getColorStateList(R.styleable.PropertyView_propertyTextColor)
titleTextView.setTextColor(colors)
For advanced needs where you want to digest the ColorStateList
yourself
- In the first 2 cases you can access the color using
colors.defaultColor
- If you used a selector you have to call the method
getColorForState
The easiest way to extract a color is by doing
val currentColor = colors.getColorForState(drawableState, colors.defaultColor)
// do whatever you want with the color
It returns the color if there is one for the current state, otherwise the default one
This last part should be placed in the drawableStateChanged()
method to be notified every time the state changes