一直觉得Android L的ProgressBar,也就是那个加载小圆圈动画非常潮,研究后发现谷歌是使用矢量图形VectorDrawable(SVG)画出图形和一些动画混合制作而成的,流畅而且生动。这里写点使用心得。
首先看下sdk里的xml源码。
<style name="Widget.Material.ProgressBar" parent="Widget.ProgressBar">
<item name="indeterminateDrawable">@drawable/progress_medium_material</item>
</style>
可以看到谷歌做了一个Material风格的drawable,再看看drawable怎么写的,
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/vector_drawable_progress_bar_medium" >
<target
android:name="progressBar"
android:animation="@anim/progress_indeterminate_material" />
<target
android:name="root"
android:animation="@anim/progress_indeterminate_rotation_material" />
</animated-vector>
这是一个animated-vector,字面上理解就是动画加矢量图形。上面drawable就是图形,下面是两个属性动画,再来看看vector_drawable_progress_bar_medium,
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="48dp"
android:width="48dp"
android:viewportHeight="48"
android:viewportWidth="48"
android:tint="?attr/colorControlActivated">
<group
android:name="root"
android:translateX="24.0"
android:translateY="24.0" >
<path
android:name="progressBar"
android:fillColor="#00000000"
android:pathData="M0, 0 m 0, -19 a 19,19 0 1,1 0,38 a 19,19 0 1,1 0,-38"
android:strokeColor="@color/white"
android:strokeLineCap="square"
android:strokeLineJoin="miter"
android:strokeWidth="4"
android:trimPathEnd="0"
android:trimPathOffset="0"
android:trimPathStart="0" />
</group>
</vector>
这里可以看到一些配置属性,大小什么的,pathData就这个绘图(SVG)的核心参数,再看下两个动画文件,
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<objectAnimator
android:duration="1333"
android:interpolator="@interpolator/trim_start_interpolator"
android:propertyName="trimPathStart"
android:repeatCount="-1"
android:valueFrom="0"
android:valueTo="0.75"
android:valueType="floatType" />
<objectAnimator
android:duration="1333"
android:interpolator="@interpolator/trim_end_interpolator"
android:propertyName="trimPathEnd"
android:repeatCount="-1"
android:valueFrom="0"
android:valueTo="0.75"
android:valueType="floatType" />
<objectAnimator
android:duration="1333"
android:interpolator="@android:anim/linear_interpolator"
android:propertyName="trimPathOffset"
android:repeatCount="-1"
android:valueFrom="0"
android:valueTo="0.25"
android:valueType="floatType" />
</set>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="6665"
android:interpolator="@android:anim/linear_interpolator"
android:propertyName="rotation"
android:repeatCount="-1"
android:valueFrom="0"
android:valueTo="720"
android:valueType="floatType" />
动画文件上理解可能是一个圆圈线条6.665秒内进行720度旋转,然后进行伸缩变换,复合成了动态的一个动画效果。
再来说说如何在项目中应用这个ProgressBar。
跟其他MaterialDesign控件和主题一样,你需要一个SupportV7兼容包或者高版本Sdk,兼容包在你的Sdk\extras\support\v7\appcompat目录下,最好保持最新。
1.在你的项目中挂载SupportV7兼容包,也就是项目的project.properties中写上android.library.reference.1=../导入的v7工程名
2.在你的style.xml里新建个ProgressBar的style,这个style继承于v7中的ProgressBar风格,他是自动根据sdk进行适配,如果高于L则会显现出MaterialDesign风格。
<style name="MyProgressBar" parent="Base.Widget.AppCompat.ProgressBar">
<item name="android:indeterminateTint">你自定义的颜色</item>
<item name="android:indeterminateTintMode">src_atop</item>
</style>
3.刚开始一直苦于不知道如何自定义这个ProgressBar颜色,后来看了源码xml中的attrs,才试出来是indeterminateTint和indeterminateTintMode两个属性共同作用的结果,TintMode是混合模式。源码如下,
<!-- Tint to apply to the indeterminate progress indicator. -->
<attr name="indeterminateTint" format="color" />
<!-- Blending mode used to apply the indeterminate progress indicator tint. -->
<attr name="indeterminateTintMode">
<!-- The tint is drawn on top of the drawable.
[Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc] -->
<enum name="src_over" value="3" />
<!-- The tint is masked by the alpha channel of the drawable. The drawable’s
color channels are thrown out. [Sa * Da, Sc * Da] -->
<enum name="src_in" value="5" />
<!-- The tint is drawn above the drawable, but with the drawable’s alpha
channel masking the result. [Da, Sc * Da + (1 - Sa) * Dc] -->
<enum name="src_atop" value="9" />
<!-- Multiplies the color and alpha channels of the drawable with those of
the tint. [Sa * Da, Sc * Dc] -->
<enum name="multiply" value="14" />
<!-- [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] -->
<enum name="screen" value="15" />
<!-- Combines the tint and drawable color and alpha channels, clamping the
result to valid color values. Saturate(S + D) -->
<enum name="add" value="16" />
</attr>
还有一些更多的自定义属性,不再赘述。
4.最后再再你的layout中加入这个控件。
<ProgressBar
style="@style/MyProgressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:visibility="visible" />
简单的控制隐藏和显示就能达到转圈加载中和加载完成的效果,十分简单。