3

I have this code from RatingBar android - custom draw runtime

It worked before which I used to change the color of a graphic on my rating control:

              vthf.rating.setOnTouchListener(new OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                  if (event.getAction() == MotionEvent.ACTION_UP) {
                     //--
                     float touchPositionX = event.getX();
                     float width = vthf.rating.getWidth();
                     float starsf = (touchPositionX / width);
                     starsf = starsf * param_final__data.score_max;
                     int starsint = (int) Math.round(starsf);
                     byte starsbyte = (byte) starsint;
                     param_final__data.score_cur = starsbyte;
                     starsf = starsint;
                     vthf.rating.setRating(starsf);
                     //--
                     int color = Color.BLACK;
                     switch (starsbyte % 4) {
                       case 0: color = Color.BLUE; break; // 4 stars
                       case 3: color = Color.GREEN; break;
                       case 2: color = Color.YELLOW; break;
                       case 1: color = Color.RED; break;
                     }
                     final LayerDrawable layerDrawable = (LayerDrawable) vthf.rating.getProgressDrawable();
                     Drawable myWrap = layerDrawable.getDrawable(2);
                     //--
                     //
                     //--
                     myWrap = DrawableCompat.wrap(myWrap);
                     //myWrap = myWrap.mutate();
                     //--
                     // myWrapMutate.setColorFilter(color, PorterDuff.Mode.SRC_IN);
                     // DrawableCompat.setTintList(myWrap, ColorStateList.valueOf(color));
                     //--
                     DrawableCompat.setTint(myWrap, color);
                     //--
                     vthf.rating.invalidate();
                  }
                  else
                  if (event.getAction() == MotionEvent.ACTION_DOWN) {
                    param_final__view.setPressed(true);
                  }
                  else
                  if (event.getAction() == MotionEvent.ACTION_CANCEL) {
                    param_final__view.setPressed(false);
                  }
                  return true;
                }
              });

I believe it stopped working after I upgraded from Android Studio 1.5.1 and all support libraries (not sure what version) - I am not 100% sure though since I am no sure I dsicovered the problem immediate or if it had been here longer.

I am tesing on Huawei P6 Android 4.4.2

My gradle is looking like his:

compileSdkVersion 23
buildToolsVersion '23'

dependencies {
    compile 'com.android.support:support-v4:+'
    compile 'com.google.android.gms:play-services:+'
    compile 'com.android.support:appcompat-v7:+'
}

My manifest has this

<uses-sdk
  android:minSdkVersion="9"
  android:targetSdkVersion="17" 
/>

This is my best lead on why the code is no longer working - but I am open to all kinds of suggestions if I am missing something obvious that could cause this unrelated to API versions.

---Note---

This code appears to tint the graphic slightly darker:

                     final LayerDrawable layerDrawable = (LayerDrawable) vthf.rating.getProgressDrawable();
                     Drawable myWrap = layerDrawable.getDrawable(2);
                     myWrap = DrawableCompat.wrap(myWrap);
                     DrawableCompat.setTint(myWrap, color);

This code has no effect:

                     final LayerDrawable layerDrawable = (LayerDrawable) vthf.rating.getProgressDrawable();
                     Drawable myWrap = layerDrawable.getDrawable(2);
                     DrawableCompat.setTint(myWrap, color);

Not sure what to make of the above. Maybe the problem is caused by something else that I do not understand. If the graphic is darkened, one would think it is kinda working... But it is the exact same darkening no matter he color - a least as far as my eye can tell.

Tom
  • 3,587
  • 9
  • 69
  • 124
  • [http://stackoverflow.com/a/30876871/4049612](http://stackoverflow.com/a/30876871/4049612) check this – Krishna May 16 '16 at 10:51
  • I believe i already tried all that (wrap, settintlist, settint, invalidateself) or am I missing something? – Tom May 16 '16 at 10:57
  • @Krishna Are you suggestion doing something like this " layerDrawable.setDrawable(2,myWrap);" ? It crashes (and was not necessary earlier) – Tom May 16 '16 at 11:16
  • I have extended the question with some more information – Tom May 16 '16 at 22:18
  • 1
    Stop using `:+` version identifiers for gradle dependencies. A new version will break the build, like in this case it did. – S.D. May 24 '16 at 13:52

3 Answers3

5

I use something like this to set the Color. Might work here as well, all objects that inherrit from View should be able to do this. This case uses ContextCompat to get to the color, but there are more ways than this to get the color you want.

View view = (findViewById(R.id.text_view_location));
view.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.wantedColor));
4

Something in AppCompat 23.3 breaks my previous solution. Anyway, you can get your rating bar back to work just by avoiding DrawableCompat#Wrap:

ratingBarB.setOnTouchListener(new View.OnTouchListener() {
    private int lastColoredProgress = 0;

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        int progress = ratingBarB.getProgress();
        if (progress != lastColoredProgress) {
            lastColoredProgress = progress;
            int color;
            switch (lastColoredProgress) {
                case 0:
                case 1:
                    color = Color.RED;
                    break;
                case 2:
                case 3:
                    color = Color.YELLOW;
                    break;
                case 4:
                default:
                    color = Color.GREEN;
                    break;
            }
            final Drawable drawable = ratingBarB.getProgressDrawable();
            if (drawable instanceof LayerDrawable) { // Lollipop and newer
                final LayerDrawable layerDrawable = (LayerDrawable) drawable;
                DrawableCompat.setTint(layerDrawable.getDrawable(2), color);
            } else {
                DrawableCompat.setTint(drawable, color);
            }
        }
        return false;
    }
});

Mikalai Daronin
  • 8,590
  • 2
  • 35
  • 47
3

When you wrap your Drawable with DrawableCompat, a new DrawableWrapper is created. You need to set the new drawable to your component.

In your code, you need to add somethink like this (just after setTint) :

layerDrawable.setCompoundDrawablesWithIntrinsicBounds(myWrap, null, null, null);
Johann67
  • 385
  • 6
  • 16
  • I am not sure how to fix the second index drawable inside vthf.rating.getProgressDrawable(); since it crashes when I try to layerDrawable.setDrawable(2,myWrap); – Tom May 16 '16 at 22:10
  • In addition, Android Studio can not resolve layerDrawable.setCompoundDrawablesWithIntrinsicBounds ... – Tom May 16 '16 at 22:17