ProgressBar drawable如何工作?

时间:2014-05-28 15:15:30

标签: android android-drawable android-progressbar

背景

我想制作一个确定的圆形进度条(意思是 android:indeterminate =" false" ),所以我搜索了互联网并找到了Romain Guy的简短回答,here

所以我抓住了代码并在示例项目中使用它:

(部分)布局文件:

<ProgressBar
    android:layout_width="50dp"
    android:layout_height="50dp"
    android:background="@color/backColor"
    android:indeterminate="false"
    android:indeterminateOnly="false"
    android:max="100"
    android:progress="33"
    android:progressDrawable="@drawable/progress" />

抽拉/ progress.xml

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

<!--    <item android:drawable="@drawable/progress_circular_background"/> -->
    <item>
        <shape  
            android:innerRadiusRatio="3.4"
            android:shape="ring"
            android:thicknessRatio="6.0" >
            <gradient
                android:endColor="#ffffffff"
                android:startColor="#ff000000"  
                android:type="sweep"
                android:useLevel="true" />

        </shape>
    </item>

    <item>
        <rotate
            android:drawable="@drawable/progress_particle"
            android:fromDegrees="0"
            android:pivotX="50%"
            android:pivotY="50%"
            android:toDegrees="360" />
    </item>

</layer-list>

屏幕截图(不完全是当前代码):

enter image description here

问题

它工作正常,但我不明白它是如何工作的。

进度条如何知道在drawables上究竟要改变什么,以及如何改变?

例如,它如何知道如何从右边的0度而不是其他地方获取戒指形状?

是否可以自定义它的工作方式?

1 个答案:

答案 0 :(得分:8)

ProgressBar通过更改关联的drawable的级别来工作。在doRefreshProgress()

final int level = (int) (scale * MAX_LEVEL);
(progressDrawable != null ? progressDrawable : d).setLevel(level);

Drawable's level基本上是一个整数,对于不同类型的Drawable子类可能有不同的含义。

  

这允许drawable基于连续变化其图像   控制器,例如显示进度或音量级别。

     

如果级别中的此更改导致Drawable的外观发生更改(因此需要无效),则返回true,否则返回false。

特别是,GradientDrawable(带useLevel="true",例如这个)使用级别值来知道应该绘制哪个部分的drawable。例如,对于从左到右的线性渐变,矩形计算如下:

final float level = st.mUseLevel ? (float) getLevel() / 10000.0f : 1.0f;    
x0 = r.left;            y0 = r.top;
x1 = level * r.right;   y1 = y0;

对于 ring 渐变(例如此渐变),该等级确定应绘制总360度角的哪个部分:

float sweep = st.mUseLevelForShape ? (360.0f * getLevel() / 10000.0f) : 360f;

简而言之,当调用setProgress()方法时,此值会更改,并且循环将逐渐填充。

对于RotateDrawable,它使用相同的机制来围绕其中心旋转progress_particle位图(它只是一个90度白点的透明正方形):

mState.mCurrentDegrees = mState.mFromDegrees +
    (mState.mToDegrees - mState.mFromDegrees) * ((float) level / MAX_LEVEL);

最后,关于“它如何知道如何仅从右边的0度采取环形部分,这只是一个常规问题。 Ring GradientDrawables从右侧开始。环路径计算中的第一行是:

// inner top
ringPath.moveTo(x + radius, y);
// outer top
ringPath.lineTo(x + radius + thickness, y);