Am having a weird behaviour when setting a Drawable
color using setColorFilter
when the Drawable
is a TextView DrawableCompound
and the TextView
is the view use to render elements on a ListView
.
The color doesn't apply to the Drawable
when i load the elements of the list for the first time
but when i scroll (down then up) the list (forcing the call to Adapter.getView()
) some of them get updated with the expected color.
What's even weird is that when i touch the list element that has the expected color it goes back to it's default color.
Here is my code :
protected class ViewHolderMesure {
Context context;
@InjectView(R.id.stationBandeau_mesureTextView) TextView measureTextViewWithIndicator;
public ViewHolderMesure(Context ctx, View view) {
ButterKnife.inject(this, view);
context = ctx;
}
public void populateViews(Measure mesure) {
measureTextViewWithIndicator.setText(mesure.toLabelAndValue());
if (mesure.getRawLevel() >= 0) {
measureTextViewWithIndicator.setTextColor(ContextCompat.getColor(context, R.color.gris_fonce));
}
else {
measureTextViewWithIndicator.setTextColor(ContextCompat.getColor(context, R.color.gris_clair));
}
if (mesure.hasSeuils()) {
Drawable indicator = measureTextViewWithIndicator.getCompoundDrawables()[0].mutate();
String hexaColor = mesure.getColor();// for instance"#45DA75" this hexa ref comes from a my data source which i get from a webservice call. I don't know how many colors they might be
indicator.setColorFilter(Color.parseColor(hexaColor), PorterDuff.Mode.SRC_ATOP);
indicator.invalidateSelf(); //FIXME: setColorFilter doesn't really set the Drawable color correctly
}
}
}
protected class MesureBandeauAdapter extends ArrayAdapter<Measure> {
public MesureBandeauAdapter(Context context, int resource) {
super(context, resource);
}
@SuppressLint("InflateParams")
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Measure mesure = getItem(position);
ViewHolderMesure viewHolderMesure;
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.bandeau_mesure_list_item, null);
viewHolderMesure = new ViewHolderMesure(getContext(), convertView);
convertView.setTag(viewHolderMesure);
}
else {
viewHolderMesure = (ViewHolderMesure) convertView.getTag();
}
viewHolderMesure.populateViews(mesure);
return convertView;
}
}
The xml TewtView and Drawable i use :
<TextView
android:id="@+id/stationBandeau_mesureTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:clickable="false"
android:focusable="false"
android:focusableInTouchMode="false"
android:padding="@dimen/stationBandeau_innerPadding"
android:text="@string/station_bandeau_libelle_hint"
android:textColor="@color/gris_fonce"
android:textSize="@dimen/stationBandeau_secondaryTextSize"
android:width="@dimen/stationBandeau_measurementWidth"
android:drawableLeft="@drawable/ic_alert_green_indicator"
android:drawablePadding="@dimen/stationBandeau_statusIndicatorSpacement"
tools:ignore="RtlHardcoded" />
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/blanc"/>
<size android:width="@dimen/stationBandeau_containerPadding"
android:height="@dimen/stationBandeau_containerPadding" />
</shape>
I've try to use a mutable Drawable
as sugested by http://www.curious-creature.com/2009/05/02/drawable-mutations/, try to invalidate the Drawable
after i set the color as sugested in https://stackoverflow.com/a/10749079/665823, etc.. with little success.
I hope someone can help me with this.
Edit
This isn't a duplicate of Change drawable color programmatically, changing alarme.setColorFilter(Color.parseColor("#45DA75"), PorterDuff.Mode.SRC_ATOP);
for alarme.setColorFilter(new PorterDuffColorFilter(Color.parseColor("#45DA75"), PorterDuff.Mode.MULTIPLY));
changes absolutely nothing to my problem. And besides from Android source code :
/**
* ...
* Convenience for {@link #setColorFilter(ColorFilter)} which constructs a
* {@link PorterDuffColorFilter}.
* ...
*/
public void setColorFilter(@ColorInt int color, @NonNull PorterDuff.Mode mode) {
setColorFilter(new PorterDuffColorFilter(color, mode));
}
Also getting the drawable from context Drawable alarme = ContextCompat.getDrawable(context, R.drawable.ic_alert_green_indicator).mutate();
and setting the drawable compound valeur.setCompoundDrawablesWithIntrinsicBounds(alarme, null, null, null);
instead of getting it from the TextView Drawable alarme = valeur.getCompoundDrawables()[0].mutate()
it's self didn't help either.