android - ShapeDrawable 作为 Android 中 RatingBar 的 progressDrawable?

标签 android android-ui ratingbar shapedrawable

我似乎无法将 ShapeDrawable 设置为 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>

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 代替此行的形状:

@drawable/ratingbar_full

最佳答案

Shape XML 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_width="wrap_content"

请记住,您需要在 ShapeDrawables 中添加一些填充,因为它们会边到边重复。

关于android - ShapeDrawable 作为 Android 中 RatingBar 的 progressDrawable?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19295088/

相关文章:

android - 自动完成文本框在建议列表中突出显示键入的字符

android - 自定义 View RatingBar 调用了 setOnTouchListener 但没有覆盖 performClick

Android - 如何为 RecyclerView 添加虚线/点线分隔线?

android - 创建等同于系统 View 的 'settings' View

android - 如何在安卓手机中使用磁传感器检测金属?

android - Android 列表中的可扩展项

java - 如何在android对话框中获取用户的评分值?

android - 滑动时获取 RatingBar 值

c# - 更改链接到 ListView 中所选项目的文本框中的值后,数据库中的表未更新

android java.langNullPointerException 空对象引用