这个迭代领了两个自定义控件的任务,阿西吧。。。。。之前没接触过啊,在网上找了一天,看了一天,发现改别人的控件总是有问题,没办法自己码一个最简单的。
效果图:
public class Ciecleview extends View { Paint textPaint,linePatit,lineColorPatit;//文字画笔、灰色刻度线画笔、带颜色的刻度线画笔 RectF oval;//外界正方形 private float sweepAngle=300; private float radius;//圆半径 //定义进度 float progress = 0; float limitAngle;//旋转角度 public Ciecleview(Context context) { super(context); } public Ciecleview(Context context, @Nullable AttributeSet attrs) { super(context, attrs); lineColorPatit =new Paint(); linePatit = new Paint(); //线宽 lineColorPatit.setStrokeWidth(3); //设置画笔抗锯齿 lineColorPatit.setAntiAlias(true); //设置画笔颜色 linePatit.setColor(Color.GRAY); //线宽 linePatit.setStrokeWidth(3); //设置画笔抗锯齿 linePatit.setAntiAlias(true); } public float getProgress() { return progress; } public void setProgress(float progress) { this.progress = progress; invalidate(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width = MeasureSpec.getSize(widthMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); //以最小值为正方形的长 int len = Math.min(width, height); radius = len/2; //实例化矩形 oval=new RectF(0,0,len,len); //设置测量高度和宽度(必须要调用,不然无效果) setMeasuredDimension(len, len); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //画圆弧的方法 // canvas.drawArc(oval, startAngle, sweepAngle, false,paint); //画刻度线的方法 drawViewLine(canvas); //画有颜色刻度线的方法 drawViewColorLine(canvas); //绘制文字 drawScoreText(canvas); } private void drawViewColorLine(Canvas canvas) { //先保存之前canvas的内容 canvas.save(); //移动canvas(X轴移动距离,Y轴移动距离) canvas.translate(radius,radius); //旋转坐标系 canvas.rotate(30); lineColorPatit.setColor(Color.GREEN); //确定每次旋转的角度 float rotateAngle=sweepAngle/60; for(int i=0;i<progress;i++){ if (i > 12 && i < 30) { lineColorPatit.setColor(Color.YELLOW); } else if (i > 29) { lineColorPatit.setColor(Color.RED); } //画一条刻度线 canvas.drawLine(0,radius,0,radius-20,lineColorPatit); canvas.rotate(rotateAngle); } //操作完成后恢复状态 canvas.restore(); } private void drawViewLine(Canvas canvas) { //先保存之前canvas的内容 canvas.save(); //移动canvas(X轴移动距离,Y轴移动距离) canvas.translate(radius,radius); //旋转坐标系 canvas.rotate(30); //确定每次旋转的角度 float rotateAngle=sweepAngle/60; for(int i=0;i<61;i++){ //画一条刻度线 canvas.drawLine(0,radius,0,radius-20,linePatit); canvas.rotate(rotateAngle); } //操作完成后恢复状态 canvas.restore(); } private void drawScoreText(Canvas canvas) { float smallRadius=radius-60; //绘制文本 textPaint=new Paint(); //设置文本居中对齐 textPaint.setTextAlign(Paint.Align.CENTER); textPaint.setColor(Color.BLUE); textPaint.setTextSize(smallRadius/2); canvas.drawText(""+limitAngle,radius,radius,textPaint); textPaint.setColor(Color.GRAY); textPaint.setTextSize(smallRadius/4); canvas.drawText("平均血糖",radius,radius-smallRadius/2,textPaint); //绘制点击优化在分数的下方 textPaint.setTextSize(smallRadius/4); canvas.drawText("mmol/L",radius,radius+smallRadius/2,textPaint); } public void startAnimator() { ObjectAnimator mAnimator = ObjectAnimator.ofFloat(this, "progress", 0, limitAngle); mAnimator.setInterpolator(new AccelerateDecelerateInterpolator()); mAnimator.setDuration(1000); mAnimator.start(); } public void changeAngle(Float LimitAngle) { limitAngle = LimitAngle; invalidate(); startAnimator(); } }
分为四个步骤:1、画整个灰色的刻度圆。2、画部分的带颜色的刻度圆,两个圆是重叠在一起的。3、根据坐标点画文字。4、给画颜色的刻度圆加上颜色。
这里就说两部分,一个是画带颜色的刻度圆,还有一个就是动画。
一、画有颜色的刻度圆
private void drawViewColorLine(Canvas canvas) { //先保存之前canvas的内容 canvas.save(); //移动canvas(X轴移动距离,Y轴移动距离) canvas.translate(radius,radius); //旋转坐标系 canvas.rotate(30); lineColorPatit.setColor(Color.GREEN); //确定每次旋转的角度 float rotateAngle=sweepAngle/60; for(int i=0;i<progress;i++){ if (i > 12 && i < 30) { lineColorPatit.setColor(Color.YELLOW); } else if (i > 29) { lineColorPatit.setColor(Color.RED); } //画一条刻度线 canvas.drawLine(0,radius,0,radius-20,lineColorPatit); canvas.rotate(rotateAngle); } //操作完成后恢复状态 canvas.restore(); }
我这里是画了61个刻度,而颜色的改变是通过数字的大小不同而去改变画笔的颜色,从而出现几种不同的颜色,上面小于12的时候画笔就是绿色,大于12小于30就是黄色,大于30就是红色,这个算法倒是根据自己的需求去自己改变。
二、动画
public void startAnimator() { ObjectAnimator mAnimator = ObjectAnimator.ofFloat(this, "progress", 0, limitAngle); mAnimator.setInterpolator(new AccelerateDecelerateInterpolator()); mAnimator.setDuration(1000); mAnimator.start(); }
这里动画用到了ObjectAnimator类,属性动画之前我没用过,也是这次看来一点,到时还得再去学习下,ObjectAnimator.ofFloat(this, "progress", 0, limitAngle)方法的第三个参数表示从0开始,第四个参数表示结束值,第二个参数是自定义的,我的理解是每一次动画时的返回值,因为这里最大值是limitAngle,每次动画就从0开始增加一点,一直到limitAngle,从而形成动画。这里还有个问题是ObjectAnimator会自动找progress,什么意思呢,就是一个控件的它透明度这个属性,ObjectAnimator自动去获取,我们不需要去管,而progress这个是我自定义的,所以我们手动去设置set和get方法。
public float getProgress() { return progress; } public void setProgress(float progress) { this.progress = progress; invalidate(); }
然后在Activity中调用,主界面就是这个圆形图在加一个按钮。
package com.example.zhonghuazheng.mycircleview; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Button; import android.widget.EditText; import com.example.zhonghuazheng.mycircleview.circle.Ciecleview; import java.util.Random; public class HomeActivity extends AppCompatActivity implements View.OnClickListener{ Ciecleview hwv;//我们自定义的原型图 Button btn;//布局的按钮 Random rand;//随机数 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_home); hwv= findViewById(R.id.hwv); btn= findViewById(R.id.btn); rand = new Random(); btn.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn: //点击事件中,调用动的方法 hwv.changeAngle((float) rand.nextInt(62)); break; } } }
好了。大功告成了,试试效果,到时再把柱状图补上。然后再写个渐变色