参考资料
学习的时候一直看的 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"/>