本文主要是介绍自定义View,仿蚂蚁芝麻分仪表盘(早前的一版),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
整理代码,发现了这个3年前写的一个view,记得当时也是参考了某大佬的博客写的,记不清了,因为这个view还是有一些知识点的,所以写下来记录一下吧
先看下最后的效果
上代码,具体的细节,在代码中参悟吧
样式
<declare-styleable name="RoundIndicatorView"><!--最大数值--><attr name="maxNum" format="integer"/><!--圆盘起始角度--><attr name="startAngle" format="integer"/><!--圆盘扫过的角度--><attr name="sweepAngle" format="integer"/></declare-styleable>
代码
package com.xinxin.applicationtest.widget;import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.SweepGradient;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;import com.xinxin.applicationtest.R;/*** Created by wxx on 2016/12/5 0005.* 作用 : 仿支付宝芝麻信用分*/public class IndicatorView extends View {private int sweepInWidth;//内圆弧宽度private int sweepOutWidth;//外圆弧宽度private int maxNum;//最大分值private int currentNum = 1;//当前分值private int startAngle;//圆弧开始的角度private int sweepAngle;//圆弧的结束的角度private int mWidth;//视图的宽private int mHeight;//视图的高private Paint paint;private Paint paint_2;private Paint paint_3;private Paint paint_4;private int radius;//圆弧半径public IndicatorView(Context context) {this(context, null);}public IndicatorView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public IndicatorView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);setBackgroundColor(0xFFFF6347);initAttr(attrs);initPaint();}private void initAttr(AttributeSet attributeSet) {TypedArray typedArray = getContext().obtainStyledAttributes(attributeSet, R.styleable.RoundIndicatorView);maxNum = typedArray.getInt(R.styleable.RoundIndicatorView_maxNum,500);startAngle = typedArray.getInt(R.styleable.RoundIndicatorView_startAngle, 160);sweepAngle = typedArray.getInt(R.styleable.RoundIndicatorView_sweepAngle, 220);sweepInWidth = dp2px(8);sweepOutWidth = dp2px(3);typedArray.recycle();}public int getCurrentNum() {return currentNum;}public void setCurrentNum(int currentNum) {this.currentNum = currentNum;invalidate();}public void setCurrentNumAnim(int num) {float duration = (float)Math.abs(num-currentNum)/maxNum *1500+500; //根据进度差计算动画时间ObjectAnimator anim = ObjectAnimator.ofInt(this,"currentNum",num);anim.setDuration((long) Math.min(duration,2000));anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {int value = (int) animation.getAnimatedValue();int color = calculateColor(value);setBackgroundColor(color);}});anim.start();}private int calculateColor(int value){setCurrentNum(value);ArgbEvaluator evealuator = new ArgbEvaluator();float fraction = 0;int color = 0;if(value <= maxNum/2){fraction = (float)value/(maxNum/2);color = (int) evealuator.evaluate(fraction,0xFFFF6347,0xFFFF8C00); //由红到橙}else {fraction = ( (float)value-maxNum/2 ) / (maxNum/2);color = (int) evealuator.evaluate(fraction,0xFFFF8C00,0xFF00CED1); //由橙到蓝}return color;}/*** 初始化所有画笔*/private void initPaint() {paint = new Paint(Paint.ANTI_ALIAS_FLAG);paint.setDither(true);paint.setStyle(Paint.Style.STROKE);paint.setColor(0xffffffff);paint_2 = new Paint(Paint.ANTI_ALIAS_FLAG);paint_3 = new Paint(Paint.ANTI_ALIAS_FLAG);paint_4 = new Paint(Paint.ANTI_ALIAS_FLAG);}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);int widthMode = MeasureSpec.getMode(widthMeasureSpec);int widthSize = MeasureSpec.getSize(widthMeasureSpec);int heightMode = MeasureSpec.getMode(heightMeasureSpec);int heightSize = MeasureSpec.getSize(heightMeasureSpec);if (widthMode == MeasureSpec.EXACTLY) {mWidth = widthSize;} else {mWidth = dp2px(300);}if (heightMode == MeasureSpec.EXACTLY) {mHeight = heightSize;} else {mHeight = dp2px(400);}setMeasuredDimension(mWidth,mHeight);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.save();radius = getMeasuredWidth()/4;canvas.translate(mWidth /2, mHeight /2);drawRound(canvas); //画内外圆弧drawScale(canvas);//画圆弧上的刻度drawIndicator(canvas);//画分值指示器drawCenterText(canvas);//画中间的字canvas.restore();}private String[] text ={"较差","中等","良好","优秀","极好"};/** 化圆弧上的刻度 */private void drawScale(Canvas canvas) {canvas.save();canvas.rotate(startAngle - 270);float count = (float)sweepAngle / 30;for (int i = 0; i <= 30; i++) {if (i % 6 == 0) {paint.setStrokeWidth(dp2px(3));canvas.drawLine(0, -radius - sweepInWidth / 2, 0, -radius + sweepInWidth / 2 + dp2px(2), paint);paint.setAlpha(0x90);drawText(canvas, String.valueOf(maxNum / 30 * i), paint);} else {paint.setStrokeWidth(dp2px(1));canvas.drawLine(0, -radius - sweepInWidth / 2, 0, -radius + sweepInWidth / 2, paint);paint.setAlpha(0x50);}if(i == 3 || i == 9 || i == 15 || i ==21 || i == 27) {drawText(canvas,text[(int)i/6],paint);}canvas.rotate(count);}canvas.restore();}/** 画刻度下方对应的分值 */private void drawText(Canvas canvas, String score, Paint paint) {paint.setStyle(Paint.Style.FILL);paint.setTextSize(dp2px(10));float width = paint.measureText(score);canvas.drawText(score,-width/2,-radius + sweepInWidth/2 + dp2px(15),paint);paint.setStyle(Paint.Style.STROKE);}private void drawRound(Canvas canvas) {//内圆canvas.save();paint.setAlpha(0x40);paint.setStrokeWidth(sweepInWidth);RectF rectf = new RectF(-radius,-radius,radius,radius);canvas.drawArc(rectf,startAngle,sweepAngle,false,paint);//外圆paint.setStrokeWidth(sweepOutWidth);int w = dp2px(10);RectF rectf2 = new RectF(-radius-w , -radius-w , radius+w , radius+w);canvas.drawArc(rectf2,startAngle,sweepAngle,false,paint);canvas.restore();}private int[] indicatorColor = {0xffffffff,0x00ffffff,0x99ffffff,0xffffffff};/** 画外边缘的分值指示器 */private void drawIndicator(Canvas canvas) {canvas.save();float sweep = (float) currentNum / (float) maxNum * sweepAngle;if(currentNum > maxNum) {sweep = sweepAngle;}SweepGradient sweepGradient = new SweepGradient(0, 0, indicatorColor, null);paint_2.setShader(sweepGradient);paint_2.setStyle(Paint.Style.STROKE);paint_2.setStrokeWidth(sweepOutWidth);int w = dp2px(10);RectF rectF = new RectF(-radius - w, -radius - w, radius + w, radius + w);canvas.drawArc(rectF,startAngle,sweep,false,paint_2);float x = (float) ((radius+dp2px(10))*Math.cos(Math.toRadians(startAngle+sweep)));float y = (float) ((radius+dp2px(10))*Math.sin(Math.toRadians(startAngle+sweep)));paint_3.setStyle(Paint.Style.FILL);paint_3.setColor(0xffffffff);paint_3.setMaskFilter(new BlurMaskFilter(dp2px(3), BlurMaskFilter.Blur.SOLID)); //需关闭硬件加速canvas.drawCircle(x,y,dp2px(3),paint_3);canvas.restore();}/** 画中间的字 */private void drawCenterText(Canvas canvas) {canvas.save();paint_4.setTextSize(radius/2);paint_4.setColor(0xffffffff);canvas.drawText(String.valueOf(currentNum),-paint_4.measureText(String.valueOf(currentNum))/2,0,paint_4);String content = "信用";if(currentNum < maxNum*1/5){content += text[0];}else if(currentNum >= maxNum*1/5 && currentNum < maxNum*2/5){content += text[1];}else if(currentNum >= maxNum*2/5 && currentNum < maxNum*3/5){content += text[2];}else if(currentNum >= maxNum*3/5 && currentNum < maxNum*4/5){content += text[3];}else if(currentNum >= maxNum*4/5){content += text[4];}paint_4.setTextSize(radius/4);Rect rect = new Rect();paint_4.getTextBounds(content,0,content.length(),rect);canvas.drawText(content,-rect.width()/2,rect.height(),paint_4);canvas.restore();}//一些工具方法protected int dp2px(int dp){return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,dp,getResources().getDisplayMetrics());}protected int sp2px(int sp){return (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,sp,getResources().getDisplayMetrics());}
}
xml中引用
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/activity_credit_view"android:layout_width="match_parent"android:layout_height="match_parent"android:fitsSystemWindows="true"android:orientation="vertical"tools:context="com.xinxin.applicationtest.CreditViewActivity"><com.xinxin.applicationtest.widget.IndicatorViewandroid:id="@+id/viewOne"android:layout_width="wrap_content"android:background="@android:color/holo_blue_dark"android:layout_height="200dp" /><EditTextandroid:id="@+id/etScore"android:layout_width="match_parent"android:layout_height="wrap_content" /><Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:onClick="start"/>
</LinearLayout>
如果使用
package com.xinxin.applicationtest;import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.EditText;import com.xinxin.applicationtest.widget.IndicatorView;public class CreditViewActivity extends AppCompatActivity {private IndicatorView viewOne;private EditText etScore;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_credit_view);viewOne = (IndicatorView)findViewById(R.id.viewOne);etScore = (EditText)findViewById(R.id.etScore);}public void start(View v) {String trim = etScore.getText().toString().trim();viewOne.setCurrentNumAnim(Integer.parseInt(trim));}
}
整理公司电脑,这开发过程中下载过很多的第三方库、demo啥玩意的,特别多,好几年了,电脑上到处都是一些第三方的代码,想着整理一下,清理清理没用的,所以基本都是把每一个demo都跑一下看看是什么东西,没用的就删了,发现了这个当时写的,觉得这个里边还有一些不错的view绘制的知识点和关键API,就写下来吧。
单看是不行的,需要参悟一下view绘制过程中的一些边、弧的算法。
还有一个是芝麻信用分分析图的 点击查看 https://blog.csdn.net/wxx_csdn/article/details/90714774
这篇关于自定义View,仿蚂蚁芝麻分仪表盘(早前的一版)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!