ProgressBar

提供两种进度显示模式:精确模式,模糊模式,效果见当前文件夹下

精确模式:可看到精确的进度(右)

模糊模式:相当于动画,用户看到到进度信息(左)

Android 竖条progressBar_模糊模式

Android 竖条progressBar_模糊模式_02

XML属性

style属性值

Widget.ProgressBar.Horizontal 横向进度条,模式由 indeterminate 属性决定
?android:attr/progressBarStyleHorizontal
Widget.ProgressBar 中号的圆形进度条(模糊模式)
?android:attr/progressBarStyle
Widget.ProgressBar.Small 小号的圆形进度条(模糊模式)
android:attr/progressBarStyleSmall
Widget.ProgressBar.Large 大号的圆形进度条(模糊模式)
?android:attr/progressBarStyleLarge
Widget.ProgressBar.Inverse 中号的圆形进度条(模糊模式), 适用于亮色背景,如白色
?android:attr/progressBarStyleInverse
Widget.ProgressBar.Small.Inverse 小号的圆形进度条(模糊模式),适用于亮色背景,如白色
?android:attr/progressBarStyleSmallInverse
Widget.ProgressBar.Large.Inverse 大号的圆形进度条(模糊模式),适用于亮色背景,如白色
?android:attr/progressBarStyleLargeInverse

?android:attr/progressBarStyleSmallTitle
?android:attr/progressBarStyle

由上可知:默认为中号圆形。Horizontal:水平,Small:小,Large:大,Inverse:适用于亮色背景

其他属性

animationResolution 必须为整形,模糊模式下动画每帧间隔的时间,无效设置
indeterminate true:模糊模式,默认false。用于水平进度条,圆形进度条只有模糊模式
indeterminateBehavior repeat:从头开始重复播放,cycle 结束一次循环后,倒序播放
indeterminateDrawable 模糊模式下的Drawable资源。可以是图片或者旋转动画
indeterminateDuration 必须为整形,模糊模式下动画周期持续时间
indeterminateOnly true:只能使用模糊模式,默认false
max 精确模式下最大值
progress 0~max之间的默认进度值
maxHeight 可选属性,设置ProgressBar视图(Drawable)的最大高度
maxWidth 可选属性,设置ProgressBar视图(Drawable)的最大宽度
minHeight 可选属性,设置ProgressBar视图(Drawable)的最小高度
minWidth 可选属性,设置ProgressBar视图(Drawable)的最小宽度
progressDrawable 精确模式下ProgressBar第一个进度条的Drawable资源
secondaryProgress 精确模式下ProgressBar第二个进度条的Drawable资源
mirrorForRtl 设置ProgressBar是否从右往左显示,适配阿拉伯等国家习惯,需在清单文件application标 签中设置android:supportsRtl=“true”,此属性才会生效
interpolator 默认动画的插值器

自定义ProgressBar

步骤

  1. 确定ProgressBar的模式
  2. 定义ProgressBar的Drawable资源(核心)
  3. 定义动画持续时间、动画重复方式以及动画的变化率(适用于模糊模式)

解析系统自带水平进度条

<style name="Widget.ProgressBar.Horizontal">
    <item name="indeterminateOnly">false</item>
    <item name="progressDrawable">@drawable/progress_horizontal</item>
    <item name="indeterminateDrawable">@drawable/progress_indeterminate_horizontal</item>
    <item name="minHeight">20dip</item>
    <item name="maxHeight">20dip</item>
    <item name="mirrorForRtl">true</item>
</style>
<!-- progress_horizontal -->
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
 
    <!-- 定义ProgressBar的背景 -->
    <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>
 
    <!-- 定义ProgressBar第二进度条的资源 -->
    <item android:id="@android:id/secondaryProgress">
        <!-- 将ShapeDrawable转换成ClipDrawable -->
        <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>
 
    <!-- 定义ProgressBar第一进度条的资源 -->
    <item android:id="@android:id/progress">
        <!-- 将ShapeDrawable转换成ClipDrawable -->
        <clip>
            <shape>
                <corners android:radius="5dip" />
                <gradient
                        android:startColor="#ffffd300"
                        android:centerColor="#ffffb600"
                        android:centerY="0.75"
                        android:endColor="#ffffcb00"
                        android:angle="270"/>
            </shape>
        </clip>
    </item>
 
</layer-list>

自定义progressDrawable

横向渐变进度条
<?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:angle="270"
                android:centerColor="#ff5a5d5a"
                android:centerY="0.75"
                android:endColor="#ff747674"
                android:startColor="#ff9d9e9d" />
        </shape>
    </item>
 
    <item android:id="@android:id/secondaryProgress">
        <clip>
            <shape>
                <corners android:radius="5dip" />
                <gradient
                    android:angle="0"
                    android:endColor="#a0ffcb00"
                    android:startColor="#80ffd300" />
            </shape>
        </clip>
    </item>
 
    <item android:id="@android:id/progress">
        <clip>
            <shape>
                <corners android:radius="5dip" />
                <gradient
                    android:angle="0"
                    android:endColor="#ffff4b00"
                    android:startColor="#ffffd300" />
            </shape>
        </clip>
    </item>
 
</layer-list>
垂直渐变进度条
<?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:angle="270"
                android:centerColor="#ff5a5d5a"
                android:centerY="0.75"
                android:endColor="#ff747674"
                android:startColor="#ff9d9e9d" />
        </shape>
    </item>
 
    <item android:id="@android:id/secondaryProgress">
        <clip
            android:clipOrientation="vertical"
            android:gravity="bottom">
            <shape>
                <corners android:radius="5dip" />
                <gradient
                    android:angle="90"
                    android:endColor="#a0ffcb00"
                    android:startColor="#80ffd300" />
            </shape>
        </clip>
    </item>
 
    <item android:id="@android:id/progress">
        <!-- 定义ClipDrawable的剪裁方向为垂直 -->
        <clip
            android:clipOrientation="vertical"
            android:gravity="bottom">
            <shape>
                <corners android:radius="5dip" />
                <gradient
                    android:angle="90"
                    android:endColor="#ffff4b00"
                    android:startColor="#ffffd300" />
            </shape>
        </clip>
    </item>
 
</layer-list>
旋转的齿轮
<!-- progress_indeterminate_rotate_gear -->
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromDegrees="0"
    android:toDegrees="360"
    android:pivotX="50%"
    android:pivotY="50%"
    android:drawable="@drawable/progress_indeterminate_gear1"/>
xml中ProgressBar标签
<ProgressBar
    android:layout_margin="20dp"
 android:indeterminateDrawable="@drawable/progress_indeterminate_rotate_gear"
    android:indeterminate="true"
    android:indeterminateDuration="3000"
    android:indeterminateBehavior="repeat"
    android:layout_width="200dp"
    android:layout_height="200dp" />

小结

style属性设置系统属性。如果是模糊模式,通过indeterminateDrawable属性指向自定义Drawable属性;如果是精确模式,通过progressDrawable属性指向自定义Drawable属性。

总结

  1. AlphaAnimation的巧妙用法
    对于动画的实现,ProgressBar巧妙地利用了AlphaAnimation不断变化的Alpha值来改变Drawable的Level属性,从而实现不同Drawable具有不同动画效果的功能,这一点应该说是ProgressBar的精华所在,动画不仅仅可以用来播放,也可以用来动态改变属性,这让我看到了PropertyAnimation的影子。我们可以利用AlphaAnimation的Alpha属性来模拟属性动画中的ValueAnimator,从而在3.0以下实现类似属性动画的效果,这个技巧在实现兼容低版本的View动画的时候很有用。
  2. 面向Drawable,而不是Canvas
    从Progressbar的实现方式上,我们可以发现它一直是利用Drawable来实现视图的,而不是使用Canvas来绘制图形,这样让ProgressBar的具有十分强的通用性和可扩展性,我们在自定义View的时候也应该多考虑使用Drawable资源,而不是一味地自己绘图。
  3. SynchronizedPool对象池的使用
    ProgressBar在频繁更新进度值的时候使用了对象池来回收资源,这样避免创建过多的对象,最大限度上减少了资源的消耗。

源码解析

待更新