思路参考网上大神的,该博客用于一起学习,谢谢^ ^
思路:
1 自定义view的步骤,根据需求extends View
重写onMeasure onLayout onDraw 测量 排版 绘制
根据需求,没有继承ViewGroup onLayout不必重写
2 onMeasure利用宽高约束获得xml中设置宽高,取最小为绘制圆弧的直径,确定圆弧所在的矩形区域,因为绘制圆的api需要传RectF对象
// oval是一个RectF对象为一个矩形
// startAngle为圆弧的起始角度
// sweepAngle为圆弧的经过角度(扫过角度)
// useCenter为圆弧是一个boolean值,为true时画的是圆弧,为false时画的是割弧
// paint为一个画笔对象
canvas.drawArc(oval,startAngle,sweepAngle,useCenter,paint);
3 绘制刻度:画布平移到圆心,旋转画布,绘制刻度。(根据实际需求灵活绘制)
4 提供对外方法,改变角度重新调用ondraw方法绘制(考虑线程)
5 提供接口,功能扩展
先贴代码,注释很全,之前先贴几个问题
view的坐标(每个view都已自己为中心)望舒大哥博客下载的:
canvas旋转 顺时针rotate方法参数为正顺时针,负数为逆时针,中心是坐标原点
code:
package com.weiyu.sharedanimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
import java.util.Timer;
import java.util.TimerTask;
/**
* 作者:haoran on https://github.com/woaigmz 2017/5/27.
* 邮箱:[email protected]
* 说明:
*/
public class DivisionCircleView extends View {
private int len;
private RectF oval;
//起始角度
private float startAngle=120;
//经过角度
private float sweepAngle=300;
// 刻度经过角度范围
private float targetAngle = 300;
private Paint paint;
private float radius;
// 绘制文字
private Paint textPaint;
// 画水球的画笔
private Paint waterPaint;
boolean useCenter = false;
public DivisionCircleView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initPaint();
}
/**
*1 初始化画笔对象
*/
private void initPaint() {
paint =new Paint();
//设置画笔颜色
paint.setColor(Color.WHITE);
//设置画笔抗锯齿
paint.setAntiAlias(true);
//让画出的图形是空心的(不填充)
paint.setStyle(Paint.Style.STROKE);
//文本画笔
textPaint = new Paint();
textPaint.setARGB(255, 255, 255, 255);
textPaint.setAntiAlias(true);
//水波纹画笔
waterPaint = new Paint();
waterPaint.setAntiAlias(true);
}
/**
*2 来测量限制view为正方形
* @param widthMeasureSpec
* @param heightMeasureSpec
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
//以最小值为刻度区域正方形的长
len = Math.min(width, height);
//确定圆弧所在的矩形区域
oval = new RectF(0, 0, len, len);
radius = len/2;
//设置测量高度和宽度
setMeasuredDimension(len,len);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 3 绘制圆弧
// oval是一个RectF对象为一个矩形
// startAngle为圆弧的起始角度
// sweepAngle为圆弧的经过角度(扫过角度)
// useCenter为圆弧是一个boolean值,为true时画的是圆弧,为false时画的是割弧
// paint为一个画笔对象
canvas.drawArc(oval,startAngle,sweepAngle,useCenter,paint);
// 4 画刻度线
drawViewLine(canvas);
}
/**
* 绘制刻度线
* @param canvas
*/
private void drawViewLine(Canvas canvas) {
canvas.save();
//移动canvas
canvas.translate(radius,radius);
//旋转canvas
canvas.rotate(30);
//普通刻度
Paint linePatin=new Paint();
//设置普通刻度画笔颜色
linePatin.setColor(Color.WHITE);
//线宽
linePatin.setStrokeWidth(2);
//设置画笔抗锯齿
linePatin.setAntiAlias(true);
/* //画一条刻度线
canvas.drawLine(0,radius,0,radius-40,linePatin);*/
//画101条刻度线
//确定每次旋转的角度
float rotateAngle=sweepAngle/99;
//绘制需要有颜色部分的画笔
Paint targetLinePatin=new Paint();
targetLinePatin.setColor(Color.GREEN);
targetLinePatin.setStrokeWidth(2);
targetLinePatin.setAntiAlias(true);
//记录已经绘制过的有色部分范围(角度float)
float hasDraw=0;
for(int i=0;i<100;i++){
/* //画一条刻度线
canvas.drawLine(0,radius,0,radius-40,linePatin);*/
//有色和无色分别用不同颜色
if (hasDraw <= targetAngle && targetAngle != 0) {
//计算已经绘制的比例
float percent=hasDraw/sweepAngle;
int red= 255-(int) (255*percent);
int green= (int) (255*percent);
//角度变化颜色值由外界传入而改变
if (onAngleColorListener!=null){
onAngleColorListener.colorListener(red,green);
}
targetLinePatin.setARGB(255,red,green,0);
canvas.drawLine(0, radius, 0, radius - 40, targetLinePatin);
} else {
canvas.drawLine(0,radius,0,radius-40,linePatin);
}
hasDraw += rotateAngle;
canvas.rotate(rotateAngle);
}
//操作完成后恢复状态
canvas.restore();
}
//判断是否在动
private boolean isRunning;
//判断是回退的状态还是前进状态
private int state = 1;
/**
* 5 根据角度变化刻度
* @param trueAngle
*/
public void changeAngle(final float trueAngle) {
if (isRunning){//如果在动直接返回
return;
}
final Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
switch (state) {
case 1://后退状态
isRunning=true;
targetAngle -= 3;
if (targetAngle <= 0) {//如果回退到0
targetAngle = 0;
//改为前进状态
state = 2;
}
break;
case 2://前进状态
targetAngle += 3;
if (targetAngle >= trueAngle) {//如果增加到指定角度
targetAngle = trueAngle;
//改为后退状态
state = 1;
isRunning=false;
//结束本次运动
timer.cancel();
}
break;
default:
break;
}
//重新绘制(子线程中使用的方法)
postInvalidate();
}
}, 500, 30);
}
private OnAngleColorListener onAngleColorListener;
public void setOnAngleColorListener(OnAngleColorListener onAngleColorListener) {
this.onAngleColorListener = onAngleColorListener;
}
public interface OnAngleColorListener{
void colorListener(int red,int green);
}
}
MainActivity
package com.weiyu.sharedanimator;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.LinearLayout;
public class MainActivity extends AppCompatActivity {
private DivisionCircleView divisionCircleView;
private LinearLayout ll_parent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ll_parent = (LinearLayout) findViewById(R.id.ll);
divisionCircleView = (DivisionCircleView) findViewById(R.id.dcv);
divisionCircleView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
divisionCircleView.changeAngle(200);
}
}); //设置角度颜色变化监听
divisionCircleView.setOnAngleColorListener(new DivisionCircleView.OnAngleColorListener() {
@Override
public void colorListener(int red, int green) {
Color color=new Color();
//通过Color对象将RGB值转为int类型
int backColor= color.argb(100,red,green,0);
//父布局设置背景
ll_parent.setBackgroundColor(backColor);
}
});
}
}
xml
<LinearLayout
android:id="@+id/ll"
android:gravity="center"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.weiyu.sharedanimator.DivisionCircleView
android:id="@+id/dcv"
android:layout_width="300dp"
android:layout_height="200dp"/>
LinearLayout>