Android自定义组件学习笔记(1)---仿网页进度条

最近公司的工作比较清闲,所以想要学习一些东西,就选择了自己一直想要学习的自定义组件。其实学习自定义组件也不是第一次了,只不过每次学习在之后的项目中却一直用不到,导致自己进入了一个学会一点过两天忘一点的尴尬境地。这次下定决心,边学习边笔记。

参考资料

http://blog.csdn.net/aigestudio/article/details/41212583/
学习的时候一直看的 AigeStudio的文章,感觉很详细

开始实战


首先写一个简单的小demo,正好有一个简单的等待条需要实现,上效果


好了现在说说实现思路
1、首相分析一下动画,显示一个弧线画圆的过程,然后是圆减少变成空白,再画圆的过程,代码实现应该画弧线,改变弧线的角度
2、还有就是需要弧线起点的一个变化

开始实现

import android.content.Context;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;

/**
 * Created by qiaoda on 2016/11/18.
 */

public class CircleProgress extends View {

    /**
     *重写构造方法,最终都走 CircleProgress(Context context, AttributeSet attrs, int defStyleAttr)构造方法
     * @param context
     */
    public CircleProgress(Context context) {
        this(context,null);
    }

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

    public CircleProgress(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

}
现在一个自定义组件已经可以说是完成了,当然你能看到的只是一片空白,之后就应该用画笔来实现一个能看见的效果了。
首先在构造方法中初始化画笔
 public CircleProgress(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initPaint();
    }

    /**
     *画笔
     */
    private Paint mPaint;

    /**
     * 初始化画笔
     */
    private void initPaint(){
        mPaint = new Paint();
        mPaint.setColor(Color.GREEN);//设置画笔颜色
        mPaint.setStrokeWidth(5);  //设置画笔宽度
        mPaint.setAntiAlias(true); // 消除锯齿
        mPaint.setStyle(Paint.Style.STROKE); // 我们这里实现画线所以设置空心
    }
好的,画笔初始化完成,下面我们开始画画。开始绘制的我们需要在onDraw(Canvas canvas)方法中来实现,前边我们初始化了画笔,相应的我们还得有画布,Canvas 就是我们的画布,下面我们用canvas.drawArc()方法来实现圆弧。

@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int centre = getWidth() / 2; // 获取圆心的x坐标
        int radius = centre - 5 / 2;// 半径
        RectF oval = new RectF(centre - radius, centre - radius, centre + radius, centre + radius); // 用于定义的圆弧的形状和大小的界限
        canvas.drawArc(oval, -90, 360, false, mPaint); // 根据进度画圆弧
    }
好了现在我们已经在界面上看机了一个绿色的小圆,总算是有东西了对不对。下面来说一下实现思路,弧线其实和圆的画法比较相似,它本身就可以看成是圆的一部分,所以肯定需要一个圆心和半径,圆心当然要选组件的中心点,在这里说明我写的这个组件宽高需要自己设定,而且最好宽高一致,半径就为宽度的一半减去画笔的宽度,不然就会有部分出去了。



下面我来说明一下 drawArc的具体参数
RectF             oval                  表示绘制的区域
flast                startAngle        表示绘制的角度,0度为最右边的点,一圈分为360度逆时针为负数,顺时针为正数
flast                sweepAngle   表示弧线经过的角度,我这里为360度也就是一圈
boolean        useCenter       表示是否与中点连线
Paint              paint                这个不用说了  就是画笔
  好了下面就让它转动起来
  @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int centre = getWidth() / 2; // 获取圆心的x坐标
        int radius = centre - 5 / 2;// 半径
        setProgress();
        RectF oval = new RectF(centre - radius, centre - radius, centre + radius, centre + radius); // 用于定义的圆弧的形状和大小的界限
        if (isPositive) {
            canvas.drawArc(oval, startOval, mProgress, false, mPaint); // 根据进度画圆弧
        } else {
            canvas.drawArc(oval, startOval, -mProgress, false, mPaint); // 根据进度画圆弧
        }
        postInvalidateDelayed(5);//每隔5毫秒刷新一次
    }


    /**
     * 判断绘制方向方向
     */
    private boolean isPositive = true;
    /**
     * 绘制点位置
     */
    private int startOval = -90;
    /**
     * 绘制弧线的角度
     */
    private int mProgress = 0;

    /**
     * 计算圆环显示进度和起点
     */
    private void setProgress() {
            if (mProgress == 360) {
                isPositive = false;
            } else if (mProgress == 0) {
                isPositive = true;
            }
            if (isPositive) {
                mProgress = mProgress + 4;
            } else {
                mProgress = mProgress - 4;
            }
            startOval += 3;
    }

现在已经转起来了,来看看效果
下面具体说一下我的视线步骤,首先我要是实现圆弧的增长和缩减,我在当它角度为360的时候知道已经画完一个圆,开始缩减的过程用isPositive判断,当它缩减的过程中应为逆时针收缩,所以在mProgress前加一个-号。然后有个一值控制绘制点的位置,startOval为绘制点,它也是不断变化的。下面给出完整代码

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;


/**
 * 自定义的圆形等待条
 * Created by qiaoda on 2016/11/17.
 */

public class UUCircleProgress extends View {

    /**
     * 第一圈的颜色
     */
    private int mCircleColor;

    /**
     * 圈的宽度
     */
    private int mCircleWidth;
    /**
     * 画笔
     */
    private Paint mPaint;
    /**
     * 当前进度
     */
    private int mProgress = 0;

    /**
     * 速度
     */
    private int mSpeed = 10;

    /**
     * 进度开始点
     */
    private int startOval = -90;
    /**
     * 判断方向
     */
    private boolean isPositive = true;
    /**
     * 判断是否开始
     */
    private boolean isStart = true;

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

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

    public UUCircleProgress(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.UUCircleProgress, defStyle, 0);
        int n = a.getIndexCount();
        for (int i = 0; i < n; i++) {
            int attr = a.getIndex(i);
            switch (attr) {
                case R.styleable.UUCircleProgress_circlecolor:
                    mCircleColor = a.getColor(attr, Color.GREEN);
                    break;
                case R.styleable.UUCircleProgress_circleWidth:
                    mCircleWidth = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(
                            TypedValue.COMPLEX_UNIT_PX, 20, getResources().getDisplayMetrics()));
                    break;
            }
        }
        a.recycle();
        initPaint();
    }

    /**
     * 初始化画笔
     */
    private void initPaint() {
        mPaint = new Paint();
        mPaint.setStrokeWidth(mCircleWidth); // 设置圆环的宽度
        mPaint.setAntiAlias(true); // 消除锯齿
        mPaint.setStyle(Paint.Style.STROKE); // 设置空心
        mPaint.setColor(mCircleColor); // 设置圆环的颜色
    }

    @Override
    protected void onDraw(Canvas canvas) {
        int centre = getWidth() / 2; // 获取圆心的x坐标
        int radius = centre - mCircleWidth / 2;// 半径
        RectF oval = new RectF(centre - radius, centre - radius, centre + radius, centre + radius); // 用于定义的圆弧的形状和大小的界限
        setProgress();
        if (isPositive) {
            canvas.drawArc(oval, startOval, mProgress, false, mPaint); // 根据进度画圆弧
        } else {
            canvas.drawArc(oval, startOval, -mProgress, false, mPaint); // 根据进度画圆弧
        }
        if (isStart) {
            //根据时间间隔刷新
            postInvalidateDelayed(mSpeed);
        }
    }

    /**
     * 计算圆环显示进度和起点
     */
    private void setProgress() {
        if(isStart){
            if (mProgress == 360) {
                isPositive = false;
            } else if (mProgress == 0) {
                isPositive = true;
            }
            if (isPositive) {
                mProgress = mProgress + 4;
            } else {
                mProgress = mProgress - 4;
            }
            startOval += 3;
        }

    }

    /**
     * 重新启动动画
     */
    public void start() {
        isStart = true;
        postInvalidate();
    }

    /**
     * 动画停止
     */
    public void stop() {
        isStart = false;
    }

    /**
     * 判断是否显示动画
     * @return
     */
    public boolean isStart(){
        mProgress = 0;
        startOval = -90;
        isPositive = true;
        return  isStart;
    }
}



<declare-styleable name="UUCircleProgress">
        <attr name="circlecolor" />
        <attr name="circleWidth" />
    </declare-styleable>



<路径.UUCircleProgress
        android:layout_width="50dp"
        android:layout_height="50dp"
        app:circlecolor="@color/whole_blue"
        android:layout_gravity="center"
        app:circleWidth="5dp"/>


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值