1

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

Not working

but when i scroll (down then up) the list (forcing the call to Adapter.getView()) some of them get updated with the expected color.

Working

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.

Community
  • 1
  • 1
Kalem
  • 1,132
  • 12
  • 33
  • I use different drawables. – Phantômaxx Nov 10 '15 at 10:03
  • @FrankN.Stein I edited my answer. I can't use predefined drawables since i don't know how many colors they might be. The hexa color comes from my data source. – Kalem Nov 10 '15 at 11:17
  • If you'd follow the provided link, you'd see there are some answers for your case - they just need to be adapted to your specific case. – Phantômaxx Nov 10 '15 at 11:19
  • I did follow your link, and tested the different answers. If you see my edit i listed the changes i made. That didn't help at all. – Kalem Nov 10 '15 at 11:25

0 Answers0