欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android 自定义控件之 ZProgressBar

程序员文章站 2022-06-09 09:29:56
...

前言

最近我的个人项目中,有一个页面需要大量用到 ProgressBar,但是每个 ProgressBar 的颜色是不确定的。

那么原生 ProgressBar 就无法满足我的需求了,因为原生 ProgressBar 的样式是根据 Drawable 来的,那么多颜色,岂不是需要创建 N 个 Drawable 文件了?并且该 ProgressBar 在 AndroidN 之前并没有动画效果,综上所述,索性去 GayHub 看看有没有好用的裤子。

看了一圈,发现有一个裤子挺好,继承自 LinearLayout 实现,很强大,代码也多,虽然能满足我的需求,但是有些过剩啊。

我的需求也不是很大,其实直接继承自 ProgressBar 就可以实现,不如自己造个*吧,既然 ProgressBar 是通过 Drawable 来指定样式的,那么我就可以直接在代码中生成 layout-list 和 shape 来实现一个可动态配置样式的 ProgressBar 了。

废话了一圈,阐述了下为什么有这个自定义控件。写到这,发现自己废话可真多啊。。。看这些话的时间都能理解完代码了。。。因为代码很简单、也非常少。。。

最终效果

首先看下最终的效果:
Android 自定义控件之 ZProgressBar

使用

XML 中:

 <com.github.airsaid.zprogressbar.widget.ZProgressBar
        android:id="@+id/progressBar"
        android:layout_width="match_parent"
        android:layout_height="20dp"
        android:max="100"
        app:zpb_backgroundColor="#999999"
        app:zpb_duration="300"
        app:zpb_progressColor="@color/colorAccent"
        app:zpb_radius="16dp"/>

代码中:

ZProgressBar mProgressBar = (ZProgressBar) findViewById(R.id.progressBar);
mProgressBar.setAnimProgress(50);

属性&方法

属性名 java方法 作用
zpb_backgroundColor setDefBackgroundColor(int color) 设置背景颜色
zpb_progressColor setProgressColor(int color) 设置进度颜色
zpb_radius setRadius(float radius) 设置背景弧度
zpb_duration setDuration(int duration) 设置动画时长

步骤

1,定义属性

首先思考下,该控件我们需要动态去控制的东西有哪些?背景色、进度颜色肯定需要,还有四周的弧度、动画的时长。思考好后,我们就可以在 values 文件夹下新建个 attrs 文件,用于编写自定义属性:

 <declare-styleable name="ZProgressBar">
        <!--背景颜色-->
        <attr name="zpb_backgroundColor" format="color"/>
        <!--进度条颜色-->
        <attr name="zpb_progressColor" format="color"/>
        <!--背景弧度-->
        <attr name="zpb_radius" format="dimension"/>
        <!--动画时长-->
        <attr name="zpb_duration" format="integer"/>
    </declare-styleable>

2,自定义类继承 ProgressBar

因为我们是对原有的 ProgressBar 进行扩展,所以我们需要自定义一个类继承自 ProgressBar:

public class ZProgressBar extends ProgressBar {

    private final Context mContext;

    public ZProgressBar(Context context) {
        this(context, null);
    }

    public ZProgressBar(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ZProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext = context;
    }

实现其构造方法,最终指向有三个参数的构造方法,在该方法内获取刚刚定义好的自定义属性,以及初始化操作:


    public ZProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext = context;
        initAttrs(attrs);
        createDrawable();
    }
 private void initAttrs(AttributeSet attrs) {
        TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.ZProgressBar);
        mBackgroundColor = a.getColor(R.styleable.ZProgressBar_zpb_backgroundColor, mBackgroundColor);
        mProgressColor = a.getColor(R.styleable.ZProgressBar_zpb_progressColor, mProgressColor);
        mRadius = a.getDimension(R.styleable.ZProgressBar_zpb_radius, mRadius);
        mDuration = a.getInt(R.styleable.ZProgressBar_zpb_duration, mDuration);
        a.recycle();
    }
private void createDrawable(){
        Drawable[] layers = new Drawable[2];
        Drawable background = makeBackground();
        Drawable progress = makeProgress();
        ClipDrawable clip = new ClipDrawable(progress
                , Gravity.LEFT, ClipDrawable.HORIZONTAL);
        layers[0] = background;
        layers[1] = clip;
        LayerDrawable layer = new LayerDrawable(layers);
        layer.setId(0, android.R.id.background);
        layer.setId(1, android.R.id.progress);
        setProgressDrawable(layer);
    }

控制 ProgressBar 的样式,主要就在 setProgressDrawable 方法上,该方法的参数为一个根节点为 layout-list 的 drawable,而该 drawable 对应的类就是 LayerDrawable,于是我们需要用代码去动态生成这个类。

在上面代码中,创建了两层 drawable,分别为背景(background)和进度(progress)用于填充到 LayerDrawable:

private Drawable makeBackground(){
    return createShape(mRadius, mBackgroundColor);
}


private Drawable makeProgress(){
    return createShape(mRadius, mProgressColor);
}

private Drawable createShape(float radius, int color){
    ShapeDrawable shape = new ShapeDrawable();
    // 设置弧度
    radius = dp2px(radius);
    float[] outerRadii = new float[]{radius, radius, radius, radius, radius, radius, radius, radius};
    RoundRectShape roundShape = new RoundRectShape(outerRadii, null, null);
    shape.setShape(roundShape);
    // 设置颜色
    shape.getPaint().setColor(color);
    return shape;
}

通过 RoundRectShape 类来设置弧度,通过改变 ShapeDrawable 类的 paint 颜色来设置颜色。

在填充进度的 drawable 时,我们还必须设置 ClipDrawable,因为 ProgressBar 的进度显示效果,就是通过该类裁剪得出来的。 该类的第二个参数,可以控制裁剪的方向,这里默认是从左往右。

在设置 layotu-list 每层的 id 时,指定好 android 包下对应的 background 和 progress id,然后将创建并填充好的 LayoutDrawable 设置到 setProgressDrawable 方法中,ProgressBar 的样式就创建好了。

源码下载

相关标签: android 控件