11

我有一个表单,它是根据从 Web 服务接收到的数据动态生成的。此 Web 服务提供创建输入元素时需要使用的图像。我很难设置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>

wherecustom_star是一个简单的 .png 图像,并带有@android:style/Widget.RatingBarRatingBar 样式。这工作正常:

工作开始

但我想custom_star动态改变。

在代码中,我尝试直接使用位图设置进度可绘制:

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

并且还通过构造一个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_stardrawable出现一次,被以下尺寸拉伸RatingBar

在此处输入图像描述

有任何想法吗?

更新:

Luksprog 在下面的回答有所改进,但我仍然遇到一些问题。现在,星形可绘制对象没有被拉伸,并且可以通过触摸设置值,但在选择 3/5 时显示如下:

没有中学

并选择了 5/5:

星星太多

我相信图像的缩放可以通过一些调整来修复,但令人讨厌的是,secondaryProgressdrawable 似乎没有设置 - 用于灰色未选择星星的 drawable。没有它,它不是很有用。

4

3 回答 3

12

有任何想法吗?

当使用默认值progressDrawableprogressDrawable通过主题设置时,一切都可以,因为在(更准确地说是RatingBar它的超类)小部件的构造函数中,将调用一个方法来从该可绘制对象中“制作图块”。ProgressBar使用该setProgressDrawable方法时,不会发生这种情况,并且如果您传递一个简单的BitmapDrawable或 a LayerDrawable(带有 simple 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宽度乘以状态位图之一的宽度与星星的数量,所以为了显示正确的星星数量,这也必须计算。

于 2013-02-23T20:16:10.160 回答
0

你的id错了,你要设置@android:id/background @android:id/secondaryProgress @android:id/progress

您还可以在包含自定义内容的 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 对象上使用来设置可以显示的最大星数

于 2013-10-02T13:02:02.493 回答
0

使用这种解决方案要容易得多:

RatingBar ratingBar = new RatingBar(new ContextThemeWrapper(context, R.style.AppTheme_RatingBar), null, 0);
于 2015-05-05T11:41:53.943 回答