【问题标题】:Constructing a RatingBar using images loaded from the web使用从 Web 加载的图像构建 RatingBar
【发布时间】:2013-02-08 06:22:10
【问题描述】:

我有一个表单,它是根据从 Web 服务接收到的数据动态生成的。此 Web 服务提供创建输入元素时需要使用的图像。我很难设置progressDrawableRatingBar。虽然 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>

其中custom_star 是一个简单的.png 图像,@android:style/Widget.RatingBar 作为 RatingBar 样式。这工作正常:

但我想动态更改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 drawable 出现一次,被RatingBar 的尺寸拉伸:

有什么想法吗?

更新:

Luksprog 在下面的回答有所改进,但我仍然遇到一些问题。现在,星形可绘制对象没有被拉伸,并且可以通过触摸设置值,但在选择 3/5 时会显示为这样:

并选择了 5/5:

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

【问题讨论】:

    标签: android android-layout ratingbar


    【解决方案1】:

    有什么想法吗?

    当使用默认的progressDrawable 或通过主题设置的progressDrawable 时,所有都可以,因为在RatingBar(更准确地说是它的超类ProgressBar)小部件的构造函数中,将调用一个方法从那个drawable“制作瓷砖”。当使用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;
    }
    

    然后您可以将此方法返回的LayerDrawablesetProgressDrawable 方法一起使用。 RatingBar 将其宽度设置为将其中一个状态位图的宽度乘以星星的数量,因此为了显示正确的星星数量,还必须计算它。

    【讨论】:

    • 好东西。这绝对对我有用,虽然我似乎无法让它设置secondaryProgress。单击时会出现星星,但不会出现未选中的灰色背景(我使用的是不同的可绘制对象,R.drawable.star_off)。
    • 虽然您的确切解决方案对我不起作用,但我按照您的建议检查了Android source code for ProgressBar,并且删除了 tileify() 方法对我来说非常有用。谢谢!
    • @blork 抱歉我发布的代码(没有太多时间),它没有完全复制该方法(我不知何故丢失了 clip 标志)。我相信你也设法让星星有正确的大小。 RatingBar 通过将其中一个位图的宽度乘以星数来设置其宽度(在自定义 RatingBaronMeasure 方法中计算应该显示正确的星数)。
    • 粉丝太棒了。几天来一直在努力解决这个问题。这写得非常好。请记住,您必须传递 3 个位图,否则您将获得 outofbounds 异常。另外,对于那些尝试使用 Drawable 并意识到您无法通过它们的人,只需使用此方法进行转换:stackoverflow.com/questions/8717333/…
    【解决方案2】:

    您的 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>
    

    您可以在 RatingBar 对象上使用setMax 来设置可以显示的最大星数

    【讨论】:

      【解决方案3】:

      这样的解决方案会容易得多:

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

      【讨论】:

        猜你喜欢
        • 2011-03-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-08-29
        • 1970-01-01
        • 1970-01-01
        • 2016-06-25
        • 1970-01-01
        相关资源
        最近更新 更多