最近在搞一个安卓项目,里边有一个功能需要用到进度条,我就想着干脆分享一下我是怎么一步步把这个进度条给弄出来的。
准备工作
我啥也不懂,就在网上到处找资料,看看人家是怎么做的。看不少文章,发现有好几种实现方法,有直接用系统自带的,有自定义View的,还有用动画的,看得我眼花缭乱。
我想着先试试系统自带的,简单省事。就在布局文件里加一个ProgressBar,设置一下样式:
<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyleHorizontal"

android:layout_width="match_parent"
android:layout_height="wrap_content" />
然后,在代码里找到这个ProgressBar,更新一下进度:
progressBar = findViewById(*);
*(progress);
这样,一个简单的水平进度条就出来。但是,这个样式实在是太普通,跟我的项目风格不太搭。我想着要不就自定义一个。
自定义View
自定义View,听起来很高大上,也没那么难。我先是看一些自定义View的教程,解一下大致的步骤:
- 自定义属性
- 测量(onMeasure)
- 绘制(onDraw)
然后,我就照葫芦画瓢,开始写代码。先是定义一个类,继承自View:
public class MyProgressBar extends View {
// ...

然后,在values文件夹下创建一个*文件,定义一些自定义属性,比如进度条的颜色、粗细、圆角等等:

<resources>
<declare-styleable name="MyProgressBar">
<attr name="progressColor" format="color" />
<attr name="progressWidth" format="dimension" />
<attr name="roundCorner" format="boolean" />
</declare-styleable>

</resources>
在MyProgressBar类里,重写onMeasure和onDraw方法。在onMeasure方法里,测量一下View的大小:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// ...
在onDraw方法里,用Canvas画一个圆角矩形作为背景,又画一个圆角矩形作为进度条:
@Override
protected void onDraw(Canvas canvas) {
// ...

在布局文件里,把原来的ProgressBar替换成MyProgressBar,设置一下自定义属性:

<*
android:id="@+id/myProgressBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:progressColor="#FF0000"
app:progressWidth="10dp"

app:roundCorner="true" />
运行一下,效果还不错,一个圆角矩形的进度条就出来。但是,总觉得还差点什么。我想着要不加个动画试试?
使用动画
用动画来实现进度条,就是用一系列连续的图片,组成一个帧动画。当需要显示进度的时候,就让动画可见;不需要的时候,就让动画不可见。
我先是找一张 loading 图片,然后在res/drawable文件夹下创建一个xml文件,定义一个动画:
<animation-list xmlns:android="*/apk/res/android"
android:oneshot="false">
<item android:drawable="@drawable/loading1" android:duration="100" />

<item android:drawable="@drawable/loading2" android:duration="100" />
<item android:drawable="@drawable/loading3" android:duration="100" />
<!-- ... -->
</animation-list>
然后,在布局文件里,加一个ImageView,把这个动画设置给它:
<ImageView
android:id="@+id/loadingImageView"
android:layout_width="wrap_content"

android:layout_height="wrap_content"
android:background="@drawable/loading_animation" />
在代码里,找到这个ImageView,启动动画:
loadingImageView = findViewById(*);
AnimationDrawable animationDrawable = (AnimationDrawable) *();
这样,一个旋转的 loading 动画就出来。当需要显示进度的时候,就让这个ImageView可见;不需要的时候,就让它不可见。我这里只是做个实验,具体与项目结合需要具体分析。
经过一番折腾,总算是把这个进度条给搞定。虽然过程有点曲折,但也学到不少东西。以后再遇到类似的需求,就不用再抓瞎。