【问题标题】:RatingBar custom Vector Drawables superimposingRatingBar 自定义 Vector Drawables 叠加
【发布时间】:2015-11-30 15:14:24
【问题描述】:

Android 中的 RatingBar 令人沮丧。

我已经按照https://stackoverflow.com/a/13107765 实现了一个带有我自己的可绘制对象的自定义评分栏,但是所有的星星只是相互叠加,所以最终只显示了一个星星。

我一辈子都想不通为什么。

编辑:PNG 绘图似乎工作正常,但是用作矢量绘图的 SVG 导致了这个问题

【问题讨论】:

  • 我使用 SVG 作为空星和填充星的矢量绘图,但是当我尝试 PNG 绘图时,它工作得很好。 Studio 处理 SVG 的方式存在一些问题。
  • 这是一个错误,这里是问题:code.google.com/p/android/issues/…
  • 您能否成功使用@harrane 下面的答案?
  • 没试过,只用了 PNG 代替
  • @IvanFork 该错误现在以“WorkingAsIntended”关闭...我不认为,这将很快得到修复。很遗憾。

标签: android ratingbar


【解决方案1】:

这是一个临时修复,直到他们在支持库中查看它(我也把它放在 gist https://gist.github.com/harrane/815e8a94d7ca75d964714228af69c60c 中)

public class RatingBarVectorFix extends RatingBar {

    private Bitmap mSampleTile;

    public RatingBarVectorFix(Context context) {
        this(context, null);
    }

    public RatingBarVectorFix(Context context, AttributeSet attrs) {
        this(context, attrs, android.support.v7.appcompat.R.attr.ratingBarStyle);
    }

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

    private void init() {
        LayerDrawable drawable = (LayerDrawable) tileify(getProgressDrawable(), false);
        drawable.findDrawableByLayerId(android.R.id.background).setColorFilter(backgroundTintColor, PorterDuff.Mode.SRC_ATOP);
        drawable.findDrawableByLayerId(android.R.id.progress).setColorFilter(progressTintColor, PorterDuff.Mode.SRC_ATOP);
        setProgressDrawable(drawable);
    }

    /**
     * Converts a drawable to a tiled version of itself. It will recursively
     * traverse layer and state list drawables.
     */
    private Drawable tileify(Drawable drawable, boolean clip) {
        if (drawable instanceof DrawableWrapper) {
            Drawable inner = ((DrawableWrapper) drawable).getWrappedDrawable();
            if (inner != null) {
                inner = tileify(inner, clip);
                ((DrawableWrapper) drawable).setWrappedDrawable(inner);
            }
        } else 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 BitmapDrawable) {
            final BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
            final Bitmap tileBitmap = bitmapDrawable.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);
            shapeDrawable.getPaint().setColorFilter(bitmapDrawable.getPaint().getColorFilter());
            return (clip) ? new ClipDrawable(shapeDrawable, Gravity.LEFT,
                    ClipDrawable.HORIZONTAL) : shapeDrawable;
        } else {
            return tileify(getBitmapDrawableFromVectorDrawable(drawable), clip);
        }

        return drawable;
    }

    private BitmapDrawable getBitmapDrawableFromVectorDrawable(Drawable drawable) {
        Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
        drawable.draw(canvas);
        return new BitmapDrawable(getResources(), bitmap);
    }

    @Override
    protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if (mSampleTile != null) {
            final int width = mSampleTile.getWidth() * getNumStars();
            setMeasuredDimension(ViewCompat.resolveSizeAndState(width, widthMeasureSpec, 0),
                    getMeasuredHeight());
        }
    }

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

【讨论】:

  • 这对我来说渲染不正确。您是提供自己的可绘制对象还是让系统处理?在布局文件中使用此类的示例会有所帮助。此外,如果您让系统使用内置的星形可绘制对象,是否有一种简单的方法来控制星形可绘制对象的大小?
  • 它可以工作,但我无法将步长设置为 0.1。例如当我想显示 0.3 时,半颗星是最小的
  • 这里是矢量无法使用 RatingBar 视图的错误报告:issuetracker.google.com/issues/37074370 它已被解析为“预期行为”,因此唯一官方支持的选项是使用渲染图像跨度>
  • 谢谢!只有您的解决方案适用于 SVG。我在这里添加了一个答案:stackoverflow.com/a/53589663/2914140.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-09-24
  • 2019-09-30
  • 1970-01-01
  • 2015-05-23
  • 2016-05-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多