问题
I am using
Android RatingBar change star colors
This line of code
LayerDrawable stars = (LayerDrawable) rating_bar.getProgressDrawable();
works fine on my Nexus 4 emulator API v21. When trying the same code on my Galaxy S4 API v19, I get the following error message:
Caused by: java.lang.ClassCastException: android.support.v7.internal.widget.TintDrawableWrapper cannot be cast to android.graphics.drawable.LayerDrawable
What is happening?
I am building with the latest build tools 22, my target API is 22 is as well.
回答1:
What happens is clearly explained in the error message :
TintDrawableWrapper cannot be cast to android.graphics.drawable.LayerDrawable
The support lib creates a wrapper in order to handle retro compatibility, you just need to take it into account. Have a look at the lib implementation, it probably wraps around a LayerDrawable
.
You will need to do something along the lines of :
LayerDrawable stars = getProgressDrawable(rating_bar);
}
private LayerDrawable getProgressDrawable(RatingBar ratingBar) {
if (Build.VERSION >= LOLLIPOP) {
return (LayerDrawable) ratingBar.getProgressDrawable();
} else {
// fetch the LayerDrawable based on Google's support implementation,
// probably a simple findViewById()
}
}
回答2:
LayerDrawable is used in API v21.
回答3:
Creating a subclass of RatingDialog and using that instead ofandroid.widget.RatingBar
worked for me. Here is the code I used.
Subclass:
public class RatingBar extends android.widget.RatingBar {
public RatingBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public RatingBar(Context context, AttributeSet attrs) {
super(context, attrs);
}
}
Then in my layouts:
<your.package.RatingBar
android:id="@+id/rating_bar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
/>
Then in the classes where you are casting the class, just use your.package.RatingBar
instead of android.widget.RatingBar
回答4:
Came accross the same issue today when creating a RatingBar programmatically. The following workaround is working for me also on Android 4.x devices using the AppCompatRatingBar:
AppCompatRatingBar rb = new AppCompatRatingBar(activity);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
layoutParams.gravity = Gravity.CENTER;
rb.setLayoutParams(layoutParams);
rb.setStepSize(1.0f);
rb.setMax(5);
LayerDrawable layerDrawable = null;
if (rb.getProgressDrawable() instanceof LayerDrawable) {
layerDrawable = (LayerDrawable) rb.getProgressDrawable();
} else if (rb.getProgressDrawable() instanceof DrawableWrapper) {
DrawableWrapper wrapper = (DrawableWrapper) rb.getProgressDrawable();
if (wrapper.getWrappedDrawable() instanceof LayerDrawable) {
layerDrawable = (LayerDrawable) wrapper.getWrappedDrawable();
}
}
if (layerDrawable != null) {
layerDrawable.getDrawable(2).setColorFilter(Color.WHITE, PorterDuff.Mode.SRC_ATOP);
layerDrawable.getDrawable(0).setColorFilter(Color.WHITE, PorterDuff.Mode.SRC_ATOP);
layerDrawable.getDrawable(1).setColorFilter(ContextCompat.getColor(activity, R.color.primary), PorterDuff.Mode.SRC_ATOP);
}
回答5:
Please try this trick, It will work fine by adding getCurrent() method to return a drawable.
RatingBar ratingBar = (RatingBar) findViewById(R.id.ratingBar);
LayerDrawable stars = (LayerDrawable) ratingBar.getProgressDrawable().getCurrent();
stars.getDrawable(2).setColorFilter(getResources().getColor(R.color.colorPrimary), PorterDuff.Mode.SRC_ATOP); stars.getDrawable(0).setColorFilter(getResources().getColor(R.color.white), PorterDuff.Mode.SRC_ATOP); stars.getDrawable(1).setColorFilter(getResources().getColor(R.color.colorPrimary), PorterDuff.Mode.SRC_ATOP);
来源:https://stackoverflow.com/questions/29078745/android-ratingbar-getprogressdrawable-doesnt-cast-to-right-class