自定义的漂亮的折线图,给大家分享一下
直接上代码
acitivity布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@mipmap/background"
tools:context="mylinear.zhang.com.mychartview.MyLineaActivity">
<mylinear.zhang.com.mychartview.utils.ChartView
android:id="@+id/mychart"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:charttitle="折线图测试"
app:introduce="折线图测试"
app:lineColor="@android:color/holo_red_light" />
</LinearLayout>
activity代码
package mylinear.zhang.com.mychartview;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import mylinear.zhang.com.mychartview.utils.ChartView;
public class MyLineaActivity extends AppCompatActivity {
private ChartView chartView;
private static final String[] XLabels = {"30", "40", "50", "60", "70", "80", "90", "100", "110", "120"};
private final String[] YLables = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
private final int[] colors = {Color.parseColor("#C01F2E"), Color.parseColor("#F26921"), Color.parseColor("#F26921"), Color.parseColor("#FCB040"), Color.parseColor("#0B9245"), Color.parseColor("#0B9245"), Color.parseColor("#FCB040"),
Color.parseColor("#F26921"), Color.parseColor("#F26921"), Color.parseColor("#C01F2E")};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_linea);
chartView = (ChartView) findViewById(R.id.mychart);
initview();
}
//初始化数据,生成20个30到120之间的随机数传入自定义控件
public void initview() {
List PHRData = new ArrayList<>();
Random random = new Random();
int PHRmax = 120, PHRmin = 30;
for (int i = 0; i < 20; i++) {
float s = random.nextInt(PHRmax) % (PHRmax - PHRmin + 1) + PHRmin;
PHRData.add(s);
}
chartView.SetInfo(YLables, XLabels, colors, PHRData, 30, 10);
}
}
接下来看自定控件的自定义属性
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MyChartView">
<attr name="charttitle" format="string"/>
<attr name="introduce" format="string"/>
<attr name="lineColor" format="color"/>
</declare-styleable>
</resources>
再看自定义折线图的代码
package mylinear.zhang.com.mychartview.utils;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
import java.util.List;
import mylinear.zhang.com.mychartview.R;
public class ChartView extends View {
private int[] colors ;
private float XPoint; // 原点的X坐标
private float YPoint; // 原点的Y坐标
private float XScale; // X的刻度长度
private float YScale; // Y的刻度长度
// private int YNumberScale;//Y轴标注刻度
private float Xmin;//X轴最大值
private float numberSpace;
private float XTextScale;
private float XLength; // X轴的长度
private float YLength; // Y轴的长度
private String[] XLabel; // X的刻度
private String[] YLabel; // Y的刻度
private List<Float> Data; // 数据
private String Title = ""; // 显示的标题
private String introduce = "";
private int linearColor;
private Paint xPaint;
private Paint yPaint;
private Paint dataPaint;
private Paint yTxtPaint;
private Paint xTxtPaint;
private Paint titlePaint;
private int screenWidth;
private int screenHeight;
private float XTextLength;
private Context mContext;
public ChartView(Context context) {
super(context);
this.mContext = context;
}
public ChartView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
this.mContext = context;
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyChartView);
Title = typedArray.getString(R.styleable.MyChartView_charttitle);
introduce = typedArray.getString(R.styleable.MyChartView_introduce);
linearColor = typedArray.getInt(R.styleable.MyChartView_lineColor, Color.parseColor("#ffffff"));
typedArray.recycle();
}
public ChartView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.mContext = context;
}
/**
* @param XLabels x轴标签
* @param YLabels y轴标签
* @param colors x轴颜色可以为每两个刻度之间设置不同的颜色
* @param AllData 数据List<Float>
* @param Xmin x轴起始值
* @param numberSpace x轴刻度之间相差数值
*/
public void SetInfo(String[] XLabels, String[] YLabels, int[] colors, List<Float> AllData, int Xmin, int numberSpace) {
this.XLabel = XLabels;
this.YLabel = YLabels;
this.Data = AllData;
this.Xmin = Xmin;
this.numberSpace = numberSpace;
this.colors=colors;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);// 重写onDraw方法
XPoint = DensityUtils.dp2px(mContext, 40);
YPoint = screenHeight - DensityUtils.dp2px(mContext, 25);
XLength = (screenWidth - DensityUtils.dp2px(mContext, 40));
YLength = (screenHeight - DensityUtils.dp2px(mContext, 50));
XScale = XLength / XLabel.length;
YScale = YLength / YLabel.length;
XTextLength = XLength / XLabel.length * XLabel.length;
XTextScale = XTextLength / XLabel.length;
xPaint = new Paint();
xPaint.setStyle(Paint.Style.STROKE);
xPaint.setAntiAlias(true);// 去锯齿
xPaint.setColor(getResources().getColor(R.color.chartviewline));// 颜色
xPaint.setStrokeWidth((float) DensityUtils.dp2px(mContext, 1));
xTxtPaint = new Paint();
xTxtPaint.setStyle(Paint.Style.STROKE);
xTxtPaint.setAntiAlias(true);// 去锯齿
xTxtPaint.setColor(Color.WHITE);// 颜色
xTxtPaint.setTextSize(DensityUtils.sp2px(mContext, 7)); // 设置轴文字大小
titlePaint = new Paint();
titlePaint.setStyle(Paint.Style.STROKE);
titlePaint.setAntiAlias(true);// 去锯齿
titlePaint.setColor(Color.WHITE);// 颜色
titlePaint.setTextSize(DensityUtils.sp2px(mContext, 20)); // 设置轴文字大小
yPaint = new Paint();
yPaint.setStyle(Paint.Style.STROKE);
yPaint.setAntiAlias(true);// 去锯齿
yPaint.setColor(getResources().getColor(R.color.white));// 颜色
yPaint.setStrokeWidth((float) DensityUtils.dp2px(mContext, 5));
yTxtPaint = new Paint();
yTxtPaint.setStyle(Paint.Style.STROKE);
yTxtPaint.setAntiAlias(true);// 去锯齿
yTxtPaint.setColor(Color.WHITE);// 颜色
yTxtPaint.setTextSize(DensityUtils.sp2px(mContext, 8)); // 设置轴文字大小
dataPaint = new Paint();
dataPaint.setStyle(Paint.Style.FILL);
dataPaint.setAntiAlias(true);// 去锯齿
dataPaint.setColor(linearColor);// 颜色
dataPaint.setTextSize(22); // 设置轴文字大小
dataPaint.setStrokeWidth(DensityUtils.dp2px(mContext, 1));
// 刻度
for (int i = 0; i < YLabel.length; i++) {
//Y轴刻度
canvas.drawText(YLabel[i], XPoint - DensityUtils.dp2px(mContext, 25), YPoint - i * YScale
+ DensityUtils.dp2px(mContext, 2), yTxtPaint); // 文字
//X轴线
canvas.drawLine(XPoint, YPoint - i * YScale, XPoint + XLength - XLength / XLabel.length, YPoint - i * YScale, xPaint);
}
//Y轴线
for (int i = 0; i < YLabel.length - 1; i++) {
if (colors!=null){
if (colors[i] != 0) {
yPaint.setColor(colors[i]);
}
}else {
yPaint.setColor(Color.WHITE);
}
canvas.drawLine(XPoint - DensityUtils.dp2px(mContext, 3), YPoint - i * YScale, XPoint - DensityUtils.dp2px(mContext, 3), YPoint - YScale * (i + 1), yPaint);
}
// 设置X轴
canvas.drawLine(XPoint, YPoint, XPoint + XLength - XLength / XLabel.length, YPoint, xPaint); // 轴线
canvas.drawText(Title, XPoint - DensityUtils.dp2px(mContext, 15), YPoint - YLength + YScale - DensityUtils.dp2px(mContext, 15), titlePaint);
Rect rect = new Rect();
titlePaint.getTextBounds(Title, 0, Title.length(), rect);
int w = rect.width();
canvas.drawText(introduce, XPoint + w, YPoint - YLength + YScale - DensityUtils.dp2px(mContext, 15), xTxtPaint);
for (int i = 0; i < XLabel.length; i++) {
canvas.drawText(XLabel[i], XPoint + i * XTextScale, YPoint + DensityUtils.dp2px(mContext, 10),
xTxtPaint); // 文字
}
drawChart(canvas);
}
private void drawChart(Canvas canvas) {
for (int i = 0; i < XLabel.length - 1; i++) {
if (Data.get(i) != null) {
canvas.drawLine(XPoint + i * XScale,
YPoint - (Data.get(i) - Xmin) / numberSpace * YScale,
XPoint + (i + 1) * XScale,
YPoint - (Data.get(i + 1) - Xmin) / numberSpace * YScale,
dataPaint);
}
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = measureWidth(widthMeasureSpec);
int height = measureHeight(heightMeasureSpec);
this.screenWidth = width;
this.screenHeight = height;
setMeasuredDimension(width, height);
}
//根据xml的设定获取宽度
private int measureWidth(int measureSpec) {
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
//wrap_content
if (specMode == MeasureSpec.AT_MOST) {
}
else if (specMode == MeasureSpec.EXACTLY) {
}
return specSize;
}
//根据xml的设定获取高度
private int measureHeight(int measureSpec) {
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
//wrap_content
if (specMode == MeasureSpec.AT_MOST) {
}
else if (specMode == MeasureSpec.EXACTLY) {
}
return specSize;
}
}