android 折线图
2019-01-19 本文已影响22人
南娇
优于别人并不高贵,真正的高贵是优于过去的自己
QQ截图20190119135102.png步骤:
一、分析折线图哪些东西是需要我们写活得
1.折线的横纵坐标数据
2.折线横纵坐标的字体颜色、大小
3.折线的颜色
4.折线上点的颜色
5.坐标轴的颜色
二、根据上面的需求我们先自定义属性,基本就是下面这些
<declare-styleable name="BrokenLineView">
<!--坐标轴颜色-->
<attr name="axisColor" format="color"/>
<!--坐标颜色-->
<attr name="coordinateColor" format="color"/>
<!--折线颜色-->
<attr name="brokenlineColor" format="color"/>
<!--坐标字体大小-->
<attr name="coordinateSize" format="dimension"/>
<!--起始的渐变色-->
<attr name="lineStartColor" format="color"/>
<!--结束的渐变色-->
<attr name="lineEndtColor" format="color"/>
</declare-styleable>
三、然后就开始自定义view
public class BrokenLineView extends View{
private Context mContext;
//坐标轴颜色
private int mAxisColor;
//坐标颜色
private int mCoordinateColor;
//折线颜色
private int mBrokenlineColor;
//坐标字体大小
private int mCoordinateTextSize;
private int mWidth,mHeight;
//坐标轴画笔
private Paint mAxisPaint;
//虚线画笔
private Paint mDashedPaint;
//折线画笔
private Paint mBrokenlinPaint;
//阴影画笔
private Paint mShaderPaint;
//渐变阴影颜色数组
private int [] shadeColors;
private int startColor;
private int endColor;
private String [] mDataX={"0","20","40","60","80","100"};
private String [] mDataY={"1","4","7","10","13","16","19","22","25","28","31"};
private String [] mDatas={"10","40","5","8","36","66","90","10","10","10","10"};
//纵坐标最宽的字体宽度
private float textMaxX=0;
//横坐标的起始Y
private float startY;
public BrokenLineView(Context context) {
this(context,null);
}
public BrokenLineView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}
public BrokenLineView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.mContext=context;
TypedArray array=context.obtainStyledAttributes(attrs, R.styleable.BrokenLineView);
mAxisColor=array.getColor(R.styleable.BrokenLineView_axisColor,mAxisColor);
mCoordinateColor=array.getColor(R.styleable.BrokenLineView_coordinateColor,mCoordinateColor);
mBrokenlineColor=array.getColor(R.styleable.BrokenLineView_brokenlineColor,mBrokenlineColor);
mCoordinateTextSize=array.getDimensionPixelSize(R.styleable.BrokenLineView_coordinateSize,mCoordinateTextSize);
startColor=array.getColor(R.styleable.BrokenLineView_lineStartColor,startColor);
endColor=array.getColor(R.styleable.BrokenLineView_lineEndtColor,endColor);
shadeColors= new int[]{startColor, endColor};
array.recycle();
//初始化画笔
initPaint();
}
private void initPaint() {
mAxisPaint=new Paint();
mAxisPaint.setColor(mAxisColor);
mAxisPaint.setAntiAlias(true);
mAxisPaint.setTextSize(mCoordinateTextSize);
mDashedPaint=new Paint();
mDashedPaint.setColor(mAxisColor);
mDashedPaint.setAntiAlias(true);
//绘制长度为2的虚线后在绘制长度为1的空白区,0位间隔
mDashedPaint.setPathEffect(new DashPathEffect(new float[]{dp2px(mContext,2),dp2px(mContext,1)},0));
mBrokenlinPaint=new Paint();
mBrokenlinPaint.setAntiAlias(true);
mBrokenlinPaint.setColor(mBrokenlineColor);
mShaderPaint=new Paint();
mShaderPaint.setAntiAlias(true);
// mShaderPaint.setColor(mBrokenlineColor);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mWidth=MeasureSpec.getSize(widthMeasureSpec);
mHeight=MeasureSpec.getSize(heightMeasureSpec);
}
@Override
protected void onDraw(Canvas canvas) {
//画坐标x
for(int i=0;i<mDataX.length;i++){
//找出最宽的纵坐标
getMaxWidth();
String textX=mDataX[i];
Paint.FontMetrics fm = mAxisPaint.getFontMetrics();
float textHeigth=fm.bottom-fm.top;
float textWidth=mAxisPaint.measureText(textX);
float x=textMaxX-textWidth;
getStartY(textHeigth);
float baseLine=(((mDataX.length-i)*(startY/mDataX.length))-textHeigth)+textHeigth-fm.bottom+textHeigth/2;
canvas.drawText(textX,x,baseLine,mAxisPaint);
//画横向虚线
setLayerType(LAYER_TYPE_SOFTWARE, null);
if(i<5){
canvas.drawLine(textMaxX+dp2px(mContext,5),startY-((i+1)*(startY/mDataX.length))
,mWidth,startY-((i+1)*(startY/mDataX.length)),mDashedPaint);
}
}
//画纵坐标
canvas.drawLine(textMaxX+dp2px(mContext,5),0,textMaxX+dp2px(mContext,5),startY,mAxisPaint);
//画横坐标
canvas.drawLine(textMaxX+dp2px(mContext,5),startY,mWidth,startY,mAxisPaint);
//画坐标轴Y
for(int i=0;i<mDataY.length;i++){
String textY=mDataY[i];
Paint.FontMetrics fm = mAxisPaint.getFontMetrics();
float textHeigth=fm.bottom-fm.top;
float textWidth=mAxisPaint.measureText(textY);
float x=textMaxX-(textWidth/2)+dp2px(mContext,5)+i*(mWidth-textMaxX+dp2px(mContext,5))/mDataY.length;
float baseLine=(mHeight-textHeigth)+textHeigth-fm.bottom-dp2px(mContext,4);
canvas.drawText(textY,x,baseLine,mAxisPaint);
//画纵向虚线
setLayerType(LAYER_TYPE_SOFTWARE, null);
canvas.drawLine(textMaxX+dp2px(mContext,5)+(i+1)*(mWidth-textMaxX+dp2px(mContext,5))/mDataY.length,startY
,textMaxX+dp2px(mContext,5)+(i+1)*(mWidth-textMaxX+dp2px(mContext,5))/mDataY.length,0,mDashedPaint);
}
//画折线
Path mPathShader=new Path();
mPathShader.moveTo(textMaxX+dp2px(mContext,5),startY);
for(int i=0;i<mDatas.length;i++){
float dataStart=Float.valueOf(mDatas[i]);
float X=textMaxX+dp2px(mContext,5)+i*(mWidth-textMaxX+dp2px(mContext,5))/mDataY.length;
float Y=startY-startY*(dataStart/100);
if((i+1)<mDatas.length){
float dataEnd=Float.valueOf(mDatas[i+1]);
float endX=textMaxX+dp2px(mContext,5)+(i+1)*(mWidth-textMaxX+dp2px(mContext,5))/mDataY.length;
float endY=startY-startY*(dataEnd/100);
canvas.drawLine(X,Y,endX,endY,mBrokenlinPaint);
}
mPathShader.lineTo(X,Y);
}
//画填充阴影
mPathShader.lineTo(textMaxX+dp2px(mContext,5)+(mDataY.length-1)*(mWidth-textMaxX+dp2px(mContext,5))/mDataY.length,startY);
Shader mShader=new LinearGradient(0, 0, 0, getHeight(), shadeColors, null, Shader.TileMode.CLAMP);
mShaderPaint.setShader(mShader);
canvas.drawPath(mPathShader,mShaderPaint);
//画折线点
for(int i=0;i<mDatas.length;i++){
float dataStart=Float.valueOf(mDatas[i]);
float X=textMaxX+dp2px(mContext,5)+i*(mWidth-textMaxX+dp2px(mContext,5))/mDataY.length;
float Y=startY-startY*(dataStart/100);
//画折点的原点
canvas.drawCircle(X,Y,dp2px(mContext,2),mBrokenlinPaint);
}
}
private void getStartY(float textHeigth) {
startY=mHeight-textHeigth-dp2px(mContext,5);
}
//找出最宽的字符串的宽度
private void getMaxWidth() {
for(int i=0;i<mDataX.length;i++){
String text=mDataX[i];
if(mAxisPaint.measureText(text)>textMaxX){
textMaxX=mAxisPaint.measureText(text);
}
}
}
private int dp2px(Context context, float dpValue) {
float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
}
上面就是自定义view的源码,注解写的很清楚,有的公共参数没有提出来,剩下的修改数据的方法自己加上就可以了