使用从Web加载的图像构建RatingBar

blo*_*ork 11 android android-layout ratingbar

我有一个表单,我从我从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>
Run Code Online (Sandbox Code Playgroud)

其中custom_star是一个简单的.png图像,并且具有@android:style/Widget.RatingBarRatingBar样式.这很好用:

工作开始

但我想custom_star动态改变.

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

Drawable d = new BitmapDrawable(getResources(), downloadedImage);
ratingBar.setProgressDrawable(d);
Run Code Online (Sandbox Code Playgroud)

并通过构建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);
Run Code Online (Sandbox Code Playgroud)

对我来说都不适用; 两者都会导致custom_star出现一次拉伸,拉伸的尺寸为RatingBar:

在此输入图像描述

有任何想法吗?

更新:

Luksprog在下面的回答有所改进,但我仍有一些问题.现在,星形drawable没有被拉伸,并且可以通过触摸设置值,但是如果选择3/5则显示为:

没有中学

和5/5选择:

太多的明星

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

Luk*_*rog 11

有任何想法吗?

当使用默认值progressDrawableprogressDrawable通过主题设置时,所有都可以,因为在RatingBar(它的超类ProgressBar更精确)小部件的构造函数中,一个方法将被调用来从该drawable"make tiles".当使用该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;
}
Run Code Online (Sandbox Code Playgroud)

然后,您将使用LayerDrawable此方法返回的setProgressDrawable方法.在RatingBar设置其宽度与星的数量的状态的位图中的一个的宽度乘以,所以为了显示分这必须以及计算出的适量.

  • @blork很抱歉我发布的代码(没有太多时间),它没有完全复制该方法(我不知何故丢失了`clip`标志).我相信你还设法使星星的大小正确.`RatingBar`通过将其中一个位图的宽度乘以星数来设置其宽度(在自定义`RatingBar`的`onMeasure`方法中计算它应该显示正确数量的星). (2认同)