Android中RatingBar的形状是否可更改为progressDrawable?

Android中RatingBar的形状是否可更改为progressDrawable?,android,android-ui,ratingbar,shapedrawable,Android,Android Ui,Ratingbar,Shapedrawable,似乎我无法将ShapedRavable设置为Ratingbar的progressDrawable。我尝试了以下操作,但失败了: <RatingBar android:id="@+id/ratingbar" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:numStars="5" android:st

似乎我无法将ShapedRavable设置为Ratingbar的progressDrawable。我尝试了以下操作,但失败了:

<RatingBar
android:id="@+id/ratingbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:numStars="5"
android:stepSize="1.0"
android:rating="3.0"
style="@style/myRatingBar"
/>

myRatingbar样式:

<style name="myRatingBar" parent="@android:style/Widget.RatingBar">
<item name="android:progressDrawable">@drawable/ratingbar_full</item>
<item name="android:indeterminateDrawable">@drawable/ratingbar_full</item>
<item name="android:minHeight">48dip</item>
<item name="android:maxHeight">48dip</item>
<item name="android:scaleType">center</item>
</style>

@可拉拔/额定杆(满)
@可拉拔/额定杆(满)
48dip
48dip
居中
ratingbar_full.xml:

    <shape 
       android:shape="ring"
       android:innerRadius="10dip"
       android:thickness="1dip">
       <solid android:color="@color/red" />
       <size
           android:width="48dip"
           android:height="48dip"
       />
    </shape>

屏幕上没有显示任何内容

编辑:此行使用.png而不是shape:

@可拉拔/额定杆(满)


您可以找到一个分步分级栏样式
尝试将
设置为图像而不是形状,如果它起作用,这意味着您的形状导致了问题

我挖掘了RatingBar(及其父类ProgressBar)源代码,发现在ProgressBar构造函数中设置progressDrawable之前调用的tileify()中缺少ShapeDrawable:

private Drawable tileify(Drawable drawable, boolean clip) {

     if (drawable instanceof LayerDrawable) {
         LayerDrawable background = (LayerDrawable) drawable;
         final int N = background.getNumberOfLayers();
         Drawable[] outDrawables = new Drawable[N];

         for (int i = 0; i < N; i++) {
             int id = background.getId(i);
             outDrawables[i] = tileify(background.getDrawable(i),
                     id == android.R.id.progress || id == android.R.id.secondaryProgress);
         }

         LayerDrawable newBg = new LayerDrawable(outDrawables);

         for (int i = 0; i < N; i++) {
             newBg.setId(i, background.getId(i));
         }

         return newBg;

     } else if (drawable instanceof StateListDrawable) {
         StateListDrawable in = (StateListDrawable) drawable;
         StateListDrawable out = new StateListDrawable();
         int numStates = in.getStateCount();
         for (int i = 0; i < numStates; i++) {
             out.addState(in.getStateSet(i), tileify(in.getStateDrawable(i), clip));
         }
         return out;

     } else if (drawable instanceof BitmapDrawable) {
         final Bitmap tileBitmap = ((BitmapDrawable) drawable).getBitmap();
         if (mSampleTile == null) {
             mSampleTile = tileBitmap;
         }

         final ShapeDrawable shapeDrawable = new ShapeDrawable(getDrawableShape());

         final BitmapShader bitmapShader = new BitmapShader(tileBitmap, Shader.TileMode.REPEAT, Shader.TileMode.CLAMP);
         shapeDrawable.getPaint().setShader(bitmapShader);

         return (clip) ? new ClipDrawable(shapeDrawable, Gravity.LEFT,
                 ClipDrawable.HORIZONTAL) : shapeDrawable;
     }

     return drawable;
}
private可绘制tileify(可绘制,布尔剪辑){
if(图层的可绘制实例可绘制){
LayerDrawable背景=(LayerDrawable)可绘制;
final int N=background.getNumberOfLayers();
可提取[]可提取=新可提取[N];
对于(int i=0;i

我不知道为什么ShapeDrawable没有放在那里,但我正在考虑在子类代码中添加它。

ShapeXML Drawables+RatingBar一团乱

这是我在不编写一个全新类的情况下所能找到的解决方案

我的扩展类根据需要为
ProgressBar
钳制它来正确构建可绘制的进度

将空状态和满状态替换为我预先填充的状态。目前不是很灵活,您可以很容易地抽象空/满星状态的设置

/**
 * Created by chris on 28/08/2014.
 * For Yoyo-Android.
 */
public class ShapeDrawableRatingBar extends RatingBar {


    /**
     * TileBitmap to base the width off of.
     */
    @Nullable
    private Bitmap mSampleTile;

    public ShapeDrawableRatingBar(final Context context, final AttributeSet attrs) {
        super(context, attrs);
        setProgressDrawable(createProgressDrawable());
    }

    @Override
    protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        if (mSampleTile != null) {
            final int width = mSampleTile.getWidth() * getNumStars();
            setMeasuredDimension(resolveSizeAndState(width, widthMeasureSpec, 0),
                    getMeasuredHeight());
        }
    }

    protected LayerDrawable createProgressDrawable() {
        final Drawable backgroundDrawable = createBackgroundDrawableShape();
        LayerDrawable layerDrawable = new LayerDrawable(new Drawable[]{
                backgroundDrawable,
                backgroundDrawable,
                createProgressDrawableShape()
        });
        layerDrawable.setId(0, android.R.id.background);
        layerDrawable.setId(1, android.R.id.secondaryProgress);
        layerDrawable.setId(2, android.R.id.progress);
        return layerDrawable;
    }

    protected Drawable createBackgroundDrawableShape() {
        final Bitmap tileBitmap = drawableToBitmap(getResources().getDrawable(R.drawable.ic_stamp_circle_empty));
        if (mSampleTile == null) {
            mSampleTile = tileBitmap;
        }
        final ShapeDrawable shapeDrawable = new ShapeDrawable(getDrawableShape());
        final BitmapShader bitmapShader = new BitmapShader(tileBitmap, Shader.TileMode.REPEAT, Shader.TileMode.CLAMP);
        shapeDrawable.getPaint().setShader(bitmapShader);
        return shapeDrawable;
    }

    protected Drawable createProgressDrawableShape() {
        final Bitmap tileBitmap = drawableToBitmap(getResources().getDrawable(R.drawable.ic_stamp_circle_full));
        final ShapeDrawable shapeDrawable = new ShapeDrawable(getDrawableShape());
        final BitmapShader bitmapShader = new BitmapShader(tileBitmap, Shader.TileMode.REPEAT, Shader.TileMode.CLAMP);
        shapeDrawable.getPaint().setShader(bitmapShader);
        return new ClipDrawable(shapeDrawable, Gravity.LEFT, ClipDrawable.HORIZONTAL);
    }

    Shape getDrawableShape() {
        final float[] roundedCorners = new float[]{5, 5, 5, 5, 5, 5, 5, 5};
        return new RoundRectShape(roundedCorners, null, null);
    }

    public static Bitmap drawableToBitmap(Drawable drawable) {
        if (drawable instanceof BitmapDrawable) {
            return ((BitmapDrawable) drawable).getBitmap();
        }

        int width = drawable.getIntrinsicWidth();
        width = width > 0 ? width : 1;
        int height = drawable.getIntrinsicHeight();
        height = height > 0 ? height : 1;

        final Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        final Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
        drawable.draw(canvas);

        return bitmap;
    }

} 
调用
setMax
setMaxStars
调用
requestLayout
,这样可以正确测量宽度。无需计算出
android:minWidth
,只需设置
android:layout\u width=“wrap\u content”


请记住,当您的
ShapeDrawables重复边到边时,您需要为它们添加一些填充。

我自定义了@ChrisJenkins方法,因此您可以设置分级栏图标的大小和分级图像的自定义色调。您可以在分级栏上设置填充或设置自定义宽度和高度@ChrisJenkins解决方案帮了我很大的忙,终于设计出了一个完全可定制的分级条。您还可以在XML中设置参数

public class DrawableRatingBar extends RatingBar
{
// TileBitmap to base the width and hight off of.
@Nullable
private Bitmap iconTile;
private float scaleIconFactor;
private @ColorInt int iconBackgroundColor;
private @ColorInt int iconForegroundColor;
private @DrawableRes int iconDrawable;

public DrawableRatingBar(Context context)
{
    super(context);
    init();
}

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

    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DrawableRatingBarItem);
    scaleIconFactor = a.getFloat(R.styleable.DrawableRatingBarItem_scaleIconFactor, 1);
    iconBackgroundColor = a.getColor(R.styleable.DrawableRatingBarItem_iconBackgroundColor, Color.BLACK);
    iconForegroundColor = a.getColor(R.styleable.DrawableRatingBarItem_iconForegroundColor, Color.WHITE);
    iconDrawable = a.getResourceId(R.styleable.DrawableRatingBarItem_iconDrawable, -1);
    a.recycle();

    init();
}

public DrawableRatingBar(Context context, AttributeSet attrs, int defStyleAttr)
{
    super(context, attrs, defStyleAttr);
    init();
}

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public DrawableRatingBar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)
{
    super(context, attrs, defStyleAttr, defStyleRes);
    init();
}

private void init()
{
    setProgressDrawable(createProgressDrawable());
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    if (iconTile != null)
    {
        final int width = iconTile.getWidth() * getNumStars();
        final int height = iconTile.getHeight();
        setMeasuredDimension(resolveSizeAndState(width, widthMeasureSpec, 0),
                             resolveSizeAndState(height, heightMeasureSpec, 0));
    }
}

protected LayerDrawable createProgressDrawable()
{
    final Drawable backgroundDrawable = createBackgroundDrawableShape();
    LayerDrawable layerDrawable = new LayerDrawable(new Drawable[] {backgroundDrawable,
                                                                    backgroundDrawable,
                                                                    createProgressDrawableShape()});
    layerDrawable.setId(0, android.R.id.background);
    layerDrawable.setId(1, android.R.id.secondaryProgress);
    layerDrawable.setId(2, android.R.id.progress);
    return layerDrawable;
}

protected Drawable createBackgroundDrawableShape()
{
    Drawable drawable = ContextCompat.getDrawable(getContext(), iconDrawable);

    final Bitmap tileBitmap = scaleImageWithColor(drawable, scaleIconFactor, iconBackgroundColor);
    if (iconTile == null)
    {
        iconTile = tileBitmap;
    }
    final ShapeDrawable shapeDrawable = new ShapeDrawable(getDrawableShape());
    final BitmapShader bitmapShader = new BitmapShader(tileBitmap, Shader.TileMode.REPEAT, Shader.TileMode.CLAMP);
    shapeDrawable.getPaint().setShader(bitmapShader);

    return shapeDrawable;
}


private void setRatingStarColor(Drawable drawable, @ColorInt int color)
{
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
    {
        DrawableCompat.setTint(drawable, color);
    }
    else
    {
        drawable.setColorFilter(color, PorterDuff.Mode.SRC_IN);
    }
}

protected Drawable createProgressDrawableShape()
{
    Drawable drawable = ContextCompat.getDrawable(getContext(), iconDrawable);

    final Bitmap tileBitmap = scaleImageWithColor(drawable, scaleIconFactor, iconForegroundColor);
    final ShapeDrawable shapeDrawable = new ShapeDrawable(getDrawableShape());
    final BitmapShader bitmapShader = new BitmapShader(tileBitmap, Shader.TileMode.REPEAT, Shader.TileMode.CLAMP);
    shapeDrawable.getPaint().setShader(bitmapShader);
    return new ClipDrawable(shapeDrawable, Gravity.LEFT, ClipDrawable.HORIZONTAL);
}

Shape getDrawableShape()
{
    return new RectShape();
}

public Bitmap scaleImageWithColor(Drawable drawable, float scaleFactor, @ColorInt int color)
{
    Bitmap b = ((BitmapDrawable) drawable).getBitmap();

    int sizeX = Math.round(drawable.getIntrinsicWidth() * scaleFactor);
    int sizeY = Math.round(drawable.getIntrinsicHeight() * scaleFactor);

    Bitmap bitmapResized = Bitmap.createScaledBitmap(b, sizeX, sizeY, true);

    Canvas canvas = new Canvas(bitmapResized);
    Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG);
    paint.setAntiAlias(true);
    ColorFilter filter = new LightingColorFilter(color, 1);
    paint.setColorFilter(filter);
    canvas.drawBitmap(bitmapResized, 0, 0, paint);

    return bitmapResized;

}

protected Bitmap fromDrawable(final Drawable drawable, final int height, final int width) {
    final Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    final Canvas canvas = new Canvas(bitmap);
    drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
    drawable.draw(canvas);
    return bitmap;
}

public float getScaleIconFactor() {
    return scaleIconFactor;
}

public void setScaleIconFactor(float scaleIconFactor) {
    this.scaleIconFactor = scaleIconFactor;
}

public int getIconForegroundColor() {
    return iconForegroundColor;
}

public void setIconForegroundColor(int iconForegroundColor) {
    this.iconForegroundColor = iconForegroundColor;
}

public int getIconBackgroundColor() {
    return iconBackgroundColor;
}

public void setIconBackgroundColor(int iconBackgroundColor) {
    this.iconBackgroundColor = iconBackgroundColor;
}

public int getIconDrawable() {
    return iconDrawable;
}

public void setIconDrawable(int iconDrawable) {
    this.iconDrawable = iconDrawable;
}

}
自定义属性:

<declare-styleable name="DrawableRatingBarItem">
    <attr name="scaleIconFactor" format="float"/>
    <attr name="iconBackgroundColor" format="color"/>
    <attr name="iconForegroundColor" format="color"/>
    <attr name="iconDrawable" format="reference"/>
</declare-styleable>


为什么位图可以,而ShapeDrawable不能?不知道!但是,由于它可以创建png的形状,并将其用于任何未来的读者都可以看到,所以它非常适合。但是,使用您使用的颜色过滤器,在将颜色添加到绘图时,它将使颜色成倍增加。我建议您使用ColorFilter=new LightingColorFilter(0,颜色);换成原来的颜色。谢谢我来看看!