Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom ratingbar on gingerbread devices

I've created a custom RatingBar, which can have 5 different colors and have rectangle bar with points below stars. Here is how it look like:

enter image description here

I am using this view in couple of places and everything is ok on Android 4.0+. But on Gingerbread I have some issues. Here is code for view class:

public class KrinsenRating extends RelativeLayout {

private TextView mRanking;
private RatingBar mStars;

public KrinsenRating(Context context, AttributeSet attrs) {
    super(context, attrs);

    LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    layoutInflater.inflate(R.layout.krinsen_rating, this);

    loadViews();
}

public KrinsenRating(Context context) {
    super(context);

    loadViews();
}

private void loadViews() {
    mRanking = (TextView) findViewById(R.id.ranking_bar_position);
    mStars = (RatingBar) findViewById(R.id.ranking_bar);
}

public void setRating(long rating){
    RatingConverter rc = new RatingConverter(rating);

    Bitmap bmp_empty = ((BitmapDrawable) getResources().getDrawable(R.drawable.star_empty)).getBitmap();
    Bitmap bmp_half = null;
    Bitmap bmp_full = null;

    switch (rc.getColor()) {
    case 1:
        bmp_half = ((BitmapDrawable) getResources().getDrawable(R.drawable.star_half1)).getBitmap();
        bmp_full = ((BitmapDrawable) getResources().getDrawable(R.drawable.star_full1)).getBitmap();

        mRanking.setBackgroundColor(getResources().getColor(R.color.ranking1));
        break;
    case 2:
        bmp_half = ((BitmapDrawable) getResources().getDrawable(R.drawable.star_half2)).getBitmap();
        bmp_full = ((BitmapDrawable) getResources().getDrawable(R.drawable.star_full2)).getBitmap();

        mRanking.setBackgroundColor(getResources().getColor(R.color.ranking2));
        break;
    case 3:
        bmp_half = ((BitmapDrawable) getResources().getDrawable(R.drawable.star_half3)).getBitmap();
        bmp_full = ((BitmapDrawable) getResources().getDrawable(R.drawable.star_full3)).getBitmap();

        mRanking.setBackgroundColor(getResources().getColor(R.color.ranking3));
        break;
    case 4:
        bmp_half = ((BitmapDrawable) getResources().getDrawable(R.drawable.star_half4)).getBitmap();
        bmp_full = ((BitmapDrawable) getResources().getDrawable(R.drawable.star_full4)).getBitmap();

        mRanking.setBackgroundColor(getResources().getColor(R.color.ranking4));
        break;
    case 5:
        bmp_half = ((BitmapDrawable) getResources().getDrawable(R.drawable.star_half5)).getBitmap();
        bmp_full = ((BitmapDrawable) getResources().getDrawable(R.drawable.star_full5)).getBitmap();

        mRanking.setBackgroundColor(getResources().getColor(R.color.ranking5));
        break;
    }

    mStars.setProgressDrawable(GUI.buildRatingBarDrawables(new Bitmap[]{bmp_empty, bmp_half, bmp_full}));
    mStars.setRating(rc.getRealRating());
    mRanking.setText(rating + "");
}
}

This line is confusing: mStars.setProgressDrawable(GUI.buildRatingBarDrawables(new Bitmap[]{bmp_empty, bmp_half, bmp_full})); but I had to have this, because of problem in rendering stars after setProgressDrawable() call (only one stretched star is showing). Here is method buildRatingBarDrawables:

public static Drawable buildRatingBarDrawables(Bitmap[] images) {
    final int[] requiredIds = { android.R.id.background,
            android.R.id.secondaryProgress, android.R.id.progress };
    final float[] roundedCorners = new float[] { 5, 5, 5, 5, 5, 5, 5, 5 };
    Drawable[] pieces = new Drawable[3];
    for (int i = 0; i < 3; i++) {
        ShapeDrawable sd = new ShapeDrawable(new RoundRectShape(
                roundedCorners, null, null));
        BitmapShader bitmapShader = new BitmapShader(images[i],
                Shader.TileMode.REPEAT, Shader.TileMode.CLAMP);
        sd.getPaint().setShader(bitmapShader);
        ClipDrawable cd = new ClipDrawable(sd, Gravity.LEFT,
                ClipDrawable.HORIZONTAL);
        if (i == 0) {
            pieces[i] = sd;
        } else {
            pieces[i] = cd;
        }
    }
    LayerDrawable ld = new LayerDrawable(pieces);
    for (int i = 0; i < 3; i++) {
        ld.setId(i, requiredIds[i]);
    }
    return ld;
}

So, everything is ok on Android ICS and newer but on Gingerbread I have some strange situations. First of all sometimes on gingerbread everything is just ok. But is often that there is no stars at all. Rectangle bar with points is always right, but stars sometimes disappears. Here is for example screen from ListView which use rating bar in every single row:

enter image description here

Like you can see, sometimes is ok, sometimes it doesn't:/ I have this rating bar on my navigation slidingMenu and there stars are shown when I slowly slide, but after slide is over (when onOpened should be call) stars are just disappear.

Have you any thougths that makes me happier with that?:)

I added xml file for rating layout:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/avatar_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center" >

<RatingBar
    android:id="@+id/ranking_bar"
    android:layout_width="wrap_content"
    android:layout_height="30dp"
    android:layout_centerHorizontal="true"
    android:clickable="false"
    android:focusable="false"
    android:isIndicator="true"
    android:numStars="3"
    android:progressDrawable="@drawable/krinsen_rating"
    android:stepSize="0.1" />

<TextView
    android:id="@+id/ranking_bar_position"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@id/ranking_bar"
    android:layout_centerHorizontal="true"
    android:contentDescription="@string/register_avatar"
    android:paddingBottom="2dp"
    android:paddingLeft="8dp"
    android:paddingRight="8dp"
    android:paddingTop="2dp"
    android:textColor="@android:color/white"
    android:textSize="14sp"
    android:textStyle="bold" />
    </RelativeLayout>
like image 406
sennin Avatar asked Nov 02 '22 15:11

sennin


1 Answers

It would be an easier approach to define your rating drawables into a layer list drawable and then assign it to your RatingBar class. It works for me on android gingerbread and before.

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+android:id/background"
          android:drawable="@drawable/star_empty" />
    <item android:id="@+android:id/secondaryProgress"
          android:drawable="@drawable/star_empty" />
    <item android:id="@+android:id/progress"
          android:drawable="@drawable/star_full" />
</layer-list>

Save that into and xml file into the drawables folder, for instance, myCustomRatingBarDrawable.xml

Then on any RatingBar view:

<RatingBar
        android:id="@+id/ratingbar"
        android:progressDrawable="@drawable/myCustomRatingBarDrawable"
        android:isIndicator="true"
        android:max="5"
        android:numStars="5"
        ...
/>
like image 107
Fernando Gallego Avatar answered Nov 12 '22 09:11

Fernando Gallego