自定义view - 折线图

自定义 view 在 Android 开发中会经常用到,本项目是一个很好的学习例子,如果有空可以看一下哟!

来看下效果图:
自定义view - 折线图_第1张图片
linechart.gif
自定义 view 代码:
/**
 * Created by kn on 2016/11/1.
 * 

* 折线图 */ public class LineChart extends View { private int mWidth, mHeight;//View 的宽和高 private float mFontSize = 12;//字体的大小 private float mStrokeWidth = 1.5f;//线条的宽度 private float mPointRadius = 2;//点的半径 private int mDateTextColor = Color.parseColor("#cfcfcf");//日期字体颜色 private int mDarkColor = Color.parseColor("#5b7fdf");//点、线的颜色(深色) private int mLightColor = Color.parseColor("#d5d8f7");//点、线的颜色(浅色) private int mShapeColor = Color.parseColor("#f3f6fd");//阴影的颜色 private String[] mXItems;//X轴的文字 private int[] mPoints;//点的数组,-1表示该日还没到 private int mLength = 7;//最大比例 private Paint mDatePaint = new Paint();//日期画笔 private Paint mPointPaint = new Paint();//点画笔 private Paint mLinePaint = new Paint();//线条画笔 private Paint mShapePaint = new Paint();//阴影部分画笔 private int max = 7; private Context mContext; public LineChart(Context context) { this(context, null); } public LineChart(Context context, AttributeSet attrs) { this(context, attrs, 0); } public LineChart(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mContext = context; TypedArray typedArray = mContext.getTheme().obtainStyledAttributes(attrs, R.styleable.LineChart, 0, 0); try { mDateTextColor = typedArray.getColor(R.styleable.LineChart_DateTextColor, mDateTextColor); mDarkColor = typedArray.getColor(R.styleable.LineChart_DarkColor, mDarkColor); mLightColor = typedArray.getColor(R.styleable.LineChart_LightColor, mLightColor); mShapeColor = typedArray.getColor(R.styleable.LineChart_ShapeColor, mShapeColor); mFontSize = typedArray.getDimensionPixelSize(R.styleable.LineChart_FontSize, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, mFontSize, mContext.getResources().getDisplayMetrics())); mStrokeWidth = typedArray.getDimensionPixelSize(R.styleable.LineChart_StrokeWidth, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, mStrokeWidth, mContext.getResources().getDisplayMetrics())); mPointRadius = typedArray.getDimensionPixelSize(R.styleable.LineChart_PointRadius, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mPointRadius, mContext.getResources().getDisplayMetrics())); } finally { typedArray.recycle(); } initPaint(); } private void initPaint() { //日期画笔 mDatePaint.setTextSize(mFontSize); mDatePaint.setColor(mDateTextColor); //点画笔 mPointPaint.setTextSize(mFontSize); mPointPaint.setColor(mDarkColor); //先画笔 mLinePaint.setAntiAlias(true); mLinePaint.setStrokeWidth(mStrokeWidth);//设置线条宽度 mLinePaint.setStyle(Paint.Style.FILL); mLinePaint.setColor(mDarkColor); //阴影部分画笔 mShapePaint.setAntiAlias(true); mShapePaint.setStyle(Paint.Style.FILL); mShapePaint.setColor(mShapeColor); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthMode = MeasureSpec.getMode(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); mWidth = widthSize; mHeight = heightSize; // if (widthMode == MeasureSpec.EXACTLY) { // mWidth = widthSize; // } else if (widthMode == MeasureSpec.AT_MOST) { // mWidth = widthSize; // } // // if (heightMode == MeasureSpec.EXACTLY) { // mHeight = heightSize; // } else if (heightMode == MeasureSpec.AT_MOST) { // mHeight = mWidth / 7 * 3; // } if (heightMode == MeasureSpec.AT_MOST) { mHeight = mWidth / 7 * 3; } setMeasuredDimension(mWidth, mHeight); } private float mAnimatedValue = 0f; protected void OnAnimationUpdate(ValueAnimator valueAnimator) { mAnimatedValue = (float) valueAnimator.getAnimatedValue(); invalidate(); } public ValueAnimator valueAnimator; private ValueAnimator startViewAnim(float startF, final float endF, long time) { valueAnimator = ValueAnimator.ofFloat(startF, endF); valueAnimator.setDuration(time); valueAnimator.setInterpolator(new LinearInterpolator()); // valueAnimator.setRepeatCount(ValueAnimator.INFINITE); // valueAnimator.setRepeatMode(ValueAnimator.RESTART); valueAnimator.setRepeatMode(ValueAnimator.REVERSE); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { OnAnimationUpdate(valueAnimator); } }); valueAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); } @Override public void onAnimationStart(Animator animation) { super.onAnimationStart(animation); } @Override public void onAnimationRepeat(Animator animation) { super.onAnimationRepeat(animation); } }); if (!valueAnimator.isRunning()) { valueAnimator.start(); } return valueAnimator; } @Override protected void onDraw(Canvas canvas) { if (mXItems == null) { mXItems = new String[]{"日", "一", "二", "三", "四", "五", "六"}; mPoints = new int[]{0, -1, -1, -1, -1, -1, -1}; mLength = mXItems.length; } //最大比例 for (int i = 0; i < mLength; i++) { if (mPoints[i] > max) { max = mPoints[i]; } } //原点坐标 int xOrigin = (int) (0.5 * (mWidth / mLength) - mFontSize / 2); int yOrigin = (int) (max * ((mHeight - mLength * mFontSize) / max) + 4 * mFontSize); int[] xPoints = new int[mLength];//x轴的刻度集合 int[] yPoints = new int[mLength];//y轴的刻度集合 canvas.save(); for (int i = 0; i < mLength; i++) { //获取点的坐标 xPoints[i] = (int) ((i + 0.5) * (mWidth / mLength)); //todo yPoints[i] = (int) ((max - (mPoints[i] == -1 ? 0 : mPoints[i]) * mAnimatedValue) * ((mHeight - mLength * mFontSize) / max) + 4 * mFontSize); if (i > 0) { //画一个实心梯形,阴影部分 Path path = new Path(); path.moveTo(xPoints[i - 1], yOrigin + mPointRadius / 2); path.lineTo(xPoints[i - 1], yPoints[i - 1]); path.lineTo(xPoints[i], yPoints[i]); path.lineTo(xPoints[i], yOrigin + mPointRadius / 2); path.close(); canvas.drawPath(path, mShapePaint); } //画出日期 canvas.drawText(mXItems[i], (int) ((i + 0.5) * mWidth / mLength) - mFontSize / 2, mHeight - mFontSize, mDatePaint); } for (int i = 0; i < mLength; i++) { if (mPoints[i] == -1) { mLinePaint.setColor(mLightColor); mPointPaint.setColor(mLightColor); } else { mLinePaint.setColor(mDarkColor); mPointPaint.setColor(mDarkColor); } if (i > 0) { //画连线 canvas.drawLine(xPoints[i - 1], yPoints[i - 1], xPoints[i], yPoints[i], mLinePaint); } //画点的数值 //todo canvas.drawText(String.valueOf(mPoints[i]).equals("-1") ? " " : new BigDecimal(String.valueOf(mPoints[i] * mAnimatedValue)).setScale(0, BigDecimal.ROUND_HALF_UP) + "" // String.valueOf(mPoints[i]) , xPoints[i] - mFontSize / 4, yPoints[i] - mFontSize, mPointPaint); } for (int i = 0; i < mLength; i++) { if (mPoints[i] == -1) { mLinePaint.setColor(mLightColor); mPointPaint.setColor(mLightColor); } else { mLinePaint.setColor(mDarkColor); mPointPaint.setColor(mDarkColor); } //画点 canvas.drawCircle(xPoints[i], yPoints[i], mPointRadius, mPointPaint); } canvas.restore(); } public void setData(List dataList) { mLength = dataList.size(); if (mLength > 0) { mXItems = new String[mLength]; mPoints = new int[mLength]; for (int i = 0; i < mLength; i++) { mPoints[i] = dataList.get(i).getPoint(); mXItems[i] = dataList.get(i).getItem(); } } startViewAnim(0f, 1f, 1000); invalidate(); } }

源码

Github - LineChart

你可能感兴趣的:(自定义view - 折线图)