Подтвердить что ты не робот

Построение RatingBar с использованием изображений, загруженных из Интернета.

У меня есть форма, которую я динамически генерирую из данных, получаемых с веб-службы. Эта веб-служба предоставляет изображения, которые необходимо использовать при создании элементов ввода. Я затрудняюсь установить progressDrawable для RatingBar. Хотя XML я могу применить пользовательское изображение, используя следующее как progressDrawable:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+android:id/background" android:drawable="@drawable/custom_star" />
    <item android:id="@+android:id/secondaryProgress" android:drawable="@drawable/custom_star" />
    <item android:id="@+android:id/progress" android:drawable="@drawable/custom_star" />
</layer-list>

где custom_star - это простое .png изображение, а @android:style/Widget.RatingBar - стиль RatingBar. Это отлично работает:

Working start

но я хочу динамически изменять custom_star.

В коде я попытался установить доступность выполнения с помощью растрового изображения напрямую:

Drawable d = new BitmapDrawable(getResources(), downloadedImage);
ratingBar.setProgressDrawable(d);

а также построением a layer-list:

LayerDrawable layerDrawable = new LayerDrawable(new Drawable[] {
    getResources().getDrawable(R.drawable.custom_star),
    getResources().getDrawable(R.drawable.custom_star),             
    getResources().getDrawable(R.drawable.custom_star)
});

layerDrawable.setId(0, android.R.id.background);
layerDrawable.setId(1, android.R.id.secondaryProgress);
layerDrawable.setId(2, android.R.id.progress);

ratingBar.setProgressDrawable(layerDrawable);

Ни для меня не работает; оба приводят к появлению custom_star, который появляется один раз, растягивается на размеры RatingBar:

enter image description here

Любые идеи?

Update:

Ответ Luksprog ниже сделал улучшение, но у меня все еще есть пара проблем. Теперь вытягиваемая звезда не растягивается, и значение может быть установлено прикосновением, но оно выглядит так, как показано на рисунке 3/5:

no secondary

и 5/5:

too many stars

Я считаю, что масштабирование изображений может быть исправлено с помощью нескольких настроек, но досадно, что secondaryProgress drawable, похоже, не задан - drawable используется для серых не выбранных звезд. Без этого он не очень полезен.

4b9b3361

Ответ 1

Любые идеи?

При использовании по умолчанию progressDrawable или progressDrawable, заданных через тему, все будет нормально, как в конструкторе для RatingBar (его суперкласс ProgressBar, а точнее) виджет будет вызываться методом "сделайте плитки" из этого доступного. При использовании метода setProgressDrawable этого не происходит, и если вы передадите простой BitmapDrawable или LayerDrawable (с простым BitmapDrawables), то Drawable будет просто растянут, чтобы покрыть область фона виджета (что вы см. информацию).

Чтобы сделать это, вам нужно вручную выполнить то, что делает RatingBar при запуске, создать плитки вместе с ClipDrawables, которые он использует. Я написал метод для этого, следуя исходному коду виджета ProgressBar:

private 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;
}

Затем вы должны использовать LayerDrawable, возвращенный этим методом, с помощью метода setProgressDrawable. RatingBar устанавливает свою ширину, умножая ширину одного из растровых изображений состояния на число звезд, поэтому, чтобы показать нужное количество звезд, это также нужно вычислить.

Ответ 2

Ваши идентификаторы ошибочны, вы должны установить @android: идентификатор/фон @android: идентификатор /secondaryProgress @android: идентификатор/прогресс

Вы также можете определить drawable в xml, содержащий вашу настройку

<?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>

И вы можете использовать setMax в объекте RatingBar для установки максимального количества звезд, которые могут отображаться

Ответ 3

Это гораздо проще при таком решении:

RatingBar ratingBar = new RatingBar(new ContextThemeWrapper(context, R.style.AppTheme_RatingBar), null, 0);