2013-02-22 59 views
11

我有一个表单,可以从Web服务接收的数据动态生成。该Web服务提供了需要用于创建输入元素的图像。我很难在设置RatingBarprogressDrawable。虽然XML我可以在使用应用自定义图像以下为progressDrawable使用从网络加载的图像构建RatingBar

<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); 

,并通过构建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

任何想法?

更新:下面

Luksprog的回答做出了改进,但我仍然有几个问题。现在,明星绘制没有被拉伸和值可通过触摸来设定,但它似乎是这样用3/5选择:

no secondary

和5/5选择:

too many stars

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

回答

11

任何想法?

当使用缺省progressDrawableprogressDrawable组通过一个主题都将是不错的方法在构造函数RatingBar(其超ProgressBar更精确)小部件的方法将被称为从“做砖”那可画。当使用setProgressDrawable方法时,这种情况不会发生,如果您通过简单的BitmapDrawableLayerDrawable(简单地使用BitmapDrawablesDrawable将被简单地拉伸以覆盖小部件的背景区域(您所知道的)。

为了使其工作,您需要手动执行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; 
} 

那么你可以使用这个方法与setProgressDrawable方法返回的LayerDrawableRatingBar设置其宽度乘以状态位图之一的宽度与恒星数量,因此为了显示恰当数量的恒星,这也必须被计算。

+0

好东西。这绝对是为我工作,虽然我似乎无法让它设置secondaryProgress。点击时出现星星,但未出现灰色的未选中背景(我正在使用不同的drawable,R.drawable.star_off)。 – blork 2013-02-26 16:24:07

+1

尽管您的确切解决方案对我无效,但我查看了[ProgressBar的Android源代码](http://grepcode.com/file_/repository.grepcode.com/java/ext/com.google.android/ android/2.3.3_r1/android/widget/ProgressBar.java /),并且翻出tileify()方法对我很好。谢谢! – blork 2013-02-28 10:09:12

+2

@blork对不起,我发布的代码(没有太多时间),它没有完全复制该方法(我不知何故丢失了'clip'标志)。我相信你也能够让星星拥有正确的尺寸。 'RatingBar'通过将其中一个位图的宽度乘以恒星数量来设置它的宽度(通过自定义的'RatingBar'的'onMeasure'方法计算该值应该显示合适的恒星数量)。 – Luksprog 2013-02-28 10:39:35

0

你的ID是错的,你必须设置 @android:ID /背景 @android:ID/secondaryProgress @android:ID /进度

您也可以定义包含您的自定义

在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对象上设置了可显示

0

它是这样的容易得多的恒星的最大量lution:

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