如何在Android中动态更改进度条背景颜色

10
我想动态更改Android中进度条的背景颜色。我按照这个教程页面末尾的“奖励”部分进行了操作:http://colintmiller.com/2010/10/how-to-add-text-over-a-progress-bar-on-android/
它可以改变颜色,但只能一次。如果调用多次,进度条就会消失。这里是代码。
这是进度条的定义:
<ProgressBar android:id="@+id/progress_bar" android:layout_width="fill_parent"
    android:layout_height="wrap_content" style="@android:style/Widget.ProgressBar.Horizontal"
    android:layout_marginRight="5dp" />

这是在res/drawable/green_progress.xml中的可绘制(drawable)定义:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

<item android:id="@android:id/background">
    <shape>
        <corners android:radius="5dip" />
        <gradient
                android:startColor="#ff9d9e9d"
                android:centerColor="#ff5a5d5a"
                android:centerY="0.75"
                android:endColor="#ff747674"
                android:angle="270"
        />
    </shape>
</item>

<item android:id="@android:id/secondaryProgress">
    <clip>
        <shape>
            <corners android:radius="5dip" />
            <gradient
                    android:startColor="#80ffd300"
                    android:centerColor="#80ffb600"
                    android:centerY="0.75"
                    android:endColor="#a0ffcb00"
                    android:angle="270"
            />
        </shape>
    </clip>
</item>
<item
    android:id="@android:id/progress">
    <clip>
        <shape>
            <corners
                android:radius="5dip" />
            <gradient
                    android:startColor="@color/greenStart"
                    android:centerColor="@color/greenMid"
                    android:centerY="0.75"
                    android:endColor="@color/greenEnd"
                    android:angle="270"
            />
        </shape>
    </clip>
</item>

</layer-list>

将颜色条目添加到 rex/values/colors.xml:

<color name="greenStart">#ff33dd44</color>
<color name="greenMid">#ff0A8815</color>
<color name="greenEnd">#ff1da130</color>

最后,在代码中:

m_bar.setProgressDrawable(getResources().getDrawable(R.drawable.green_progress));  

问题是它第一次运行时有效,但然后使柱形图消失。


包含可绘制定义的文件的确切名称是什么?您的问题说它是“res/drawable/green_xml”,但是您将可绘制项设置为R.drawable.green_progress。如果您将可绘制项设置为R.drawable.green_progress,我希望您的文件名为“res/drawable/green_progress.xml”。 - plainjimbo
谢谢,没错。我刚刚纠正了它。 - Jack BeNimble
你是在哪里调用 m_bar.setProgressDrawable(...) 方法的?你是在 onCreate(..) 方法内部吗? - plainjimbo
@james - 不幸的是,那只是帖子上的一个错别字。 - Jack BeNimble
@james - 我最初是在 onResume 方法中设置它的,但随后同样的方法被从按钮点击中调用。 - Jack BeNimble
2个回答

23

请参见Android ProgressBar.setProgressDrawable只能使用一次?中的回答,以下是重复内容:

我的发现是在调用setprogressdrawable时,该可绘制对象并不知道自己的大小。当它被初始化设置时,它确实知道自己的大小。这意味着会有一个新的可绘制对象被设置到seekbar中,但可绘制对象的大小为0,因此您看不到任何东西。

解决方案是首先获取当前可绘制对象的边界,然后设置新的可绘制对象,并最后再次设置边界:

Rect bounds = mySeekBar.getProgressDrawable().getBounds();
mySeekBar.setProgressDrawable(newSeekBarBackground);
mySeekBar.getProgressDrawable().setBounds(bounds);

啊,这很有道理。我想我一开始误解了你的意图。实际上,在尝试进行自定义地图叠加时,我也遇到了完全相同的问题/修复。虽然情况不同,但根本问题是Drawable不知道它的大小。+1 - plainjimbo
詹姆斯,你之前解决了这个问题吗?我查看了ProgressBar的源代码,但它执行了一些看起来比较模糊的操作,例如requestLayout()和postInvalidate()。我想知道你是如何追踪解决方案的,以备将来参考。提前感谢! - Jack BeNimble
1
所以,我通过调试器和层次结构查看器工具的组合追踪了这个问题。在显示我的ImageView(使用drawable)之后,我在层次结构查看器中查找视图,以确保它存在,结果发现它确实存在。我注意到其尺寸为0。然后我在Stack Overflow上进行了搜索。 - plainjimbo
啊,没错。所以你已经加载了调试器的Android源代码?也许我应该试一试。 - Jack BeNimble
1
不,我没有加载Android源代码进行调试。我只是逐步执行自己的代码,在那里我动态添加了视图。调试更多的是为了确保事情是正确的,它们确实是的,更多的是层次结构查看器让我走上了0维路径。然而,调试器总是第一个我回去的地方。但是,如果你想了解'invalidate()'和其他方法的作用,调试源代码肯定是最好的方法。祝你好运 :) - plainjimbo

11

好的,对于任何想要以编程方式完成此操作的人:

    Drawable bckgrndDr = new ColorDrawable(Color.RED);
    Drawable secProgressDr = new ColorDrawable(Color.GRAY);
    Drawable progressDr = new ScaleDrawable(new ColorDrawable(Color.BLUE), Gravity.LEFT, 1, -1);
    LayerDrawable resultDr = new LayerDrawable(new Drawable[] { bckgrndDr, secProgressDr, progressDr });

    resultDr.setId(0, android.R.id.background);
    resultDr.setId(1, android.R.id.secondaryProgress);
    resultDr.setId(2, android.R.id.progress);

    progressBar.setProgressDrawable(resultDr);

给可绘制对象设置ID非常重要,可以保留进度条的边界和实际状态。


完美运行。只需按照此代码进行操作,并根据需要更改颜色。 - Khay

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接