カスタム折れ線グラフ、アリの富を模倣
9346 ワード
// , , mWidth、mBaseHeight。
protected final float DEF_WIDTH = 650;
protected final float DEF_HIGHT = 400;
// , onMeasure 。
protected int mBaseWidth;
protected int mBaseHeight;
private Paint mInnerXPaint;
private Paint mLoadingPaint;
private Paint mXYPaint;
private Paint mLinePaint;
private Paint dotPaint;
// padding,
//x、y
protected float mXYTextSize = 25;
//
protected float mLeftTxtPadding = 64;
//
protected float mBottomTxtPadding = 40;
protected float mBasePaddingTop = 200;
protected float mBasePaddingBottom = 200;
protected float mBasePaddingLeft = 150;
protected float mBasePaddingRight = 50;
private ArrayList mPoints;
private float mPerX;
private float mPerY;
public ChartView(Context context) {
this(context, null);
}
public ChartView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public ChartView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
if (widthSpecMode == AT_MOST && heightSpecMode == AT_MOST) {
setMeasuredDimension((int) DEF_WIDTH, (int) DEF_HIGHT);
} else if (widthSpecMode == AT_MOST) {
setMeasuredDimension((int) DEF_WIDTH, heightSpecSize);
} else if (heightSpecMode == AT_MOST) {
setMeasuredDimension(widthSpecSize, (int) DEF_HIGHT);
} else {
setMeasuredDimension(widthSpecSize, heightSpecSize);
}
mBaseWidth = getMeasuredWidth();
mBaseHeight = getMeasuredHeight();
}
/**
*
*/
private void init() {
//
mLoadingPaint = new Paint();
mLoadingPaint.setColor(getContext().getResources().getColor(R.color.colorAccent));
mLoadingPaint.setTextSize(14);
mLoadingPaint.setAntiAlias(true);
// x
mInnerXPaint = new Paint();
mInnerXPaint.setColor(Color.LTGRAY);
mInnerXPaint.setStrokeWidth(1);
mInnerXPaint.setStyle(Paint.Style.STROKE);
mInnerXPaint.setAntiAlias(true);
//x y
mXYPaint = new Paint();
mXYPaint.setColor(Color.GRAY);
mXYPaint.setTextSize(25);
mXYPaint.setAntiAlias(true);
//
mLinePaint = new Paint();
mLinePaint.setColor(Color.RED);
mLinePaint.setStyle(Paint.Style.STROKE);
mLinePaint.setAntiAlias(true);
mLinePaint.setTextSize(11);
//
dotPaint = new Paint();
dotPaint.setColor(Color.BLUE);
dotPaint.setStrokeWidth(1);
dotPaint.setAntiAlias(true);
}
@Override
protected void onDraw(Canvas canvas) {
// X
drawInnerXPaint(canvas);
// xy
drawXYPaint(canvas);
//
drawBrokenPaint(canvas);
//
drawDot(canvas);
}
/**
*
*
* @param canvas
*/
private void drawDot(Canvas canvas) {
// 60
float buyXDot = mBasePaddingLeft + (4 * mPerX);
float buyYDot = (mBaseHeight - mBasePaddingTop) - (mPoints.get(4).y * mPerY);
//
dotPaint.setStrokeWidth(Utils.dip2px(getContext(), 1));
canvas.drawLine(buyXDot, buyYDot, buyXDot, buyYDot - Utils.dip2px(getContext(), 20), dotPaint); //
dotPaint.setStrokeWidth(Utils.dip2px(getContext(), 4));
canvas.drawCircle(buyXDot, buyYDot, Utils.dip2px(getContext(), 2), dotPaint); //
dotPaint.setStrokeWidth(Utils.dip2px(getContext(), 0.5f));
dotPaint.setStyle(Paint.Style.FILL);
canvas.drawRect(buyXDot - Utils.dip2px(getContext(), 30), buyYDot - Utils.dip2px(getContext(), 26),
buyXDot, buyYDot - Utils.dip2px(getContext(), 13), dotPaint);
dotPaint.setTextSize(Utils.dip2px(getContext(), 11));
dotPaint.setColor(Color.WHITE);
canvas.drawText(" ", buyXDot - Utils.dip2px(getContext(), 30 / 2) - dotPaint.measureText(" ") / 2, buyYDot - Utils.dip2px(getContext(), 15), dotPaint);
float saleXDot = mBasePaddingLeft + (20 * mPerX);
float saleYDot = (mBaseHeight - mBasePaddingTop) - (mPoints.get(20).y * mPerY);
//
dotPaint.setColor(Color.GREEN);
dotPaint.setStrokeWidth(Utils.dip2px(getContext(), 1));
canvas.drawLine(saleXDot, saleYDot, saleXDot, saleYDot - Utils.dip2px(getContext(), 20), dotPaint); //
dotPaint.setStrokeWidth(Utils.dip2px(getContext(), 4));
canvas.drawCircle(saleXDot, saleYDot, Utils.dip2px(getContext(), 2), dotPaint); //
dotPaint.setStrokeWidth(Utils.dip2px(getContext(), 0.5f));
dotPaint.setStyle(Paint.Style.FILL);
canvas.drawRect(saleXDot - Utils.dip2px(getContext(), 30), saleYDot - Utils.dip2px(getContext(), 26),
saleXDot, saleYDot - Utils.dip2px(getContext(), 13), dotPaint);
dotPaint.setTextSize(Utils.dip2px(getContext(), 11));
dotPaint.setColor(Color.WHITE);
canvas.drawText(" ", saleXDot - Utils.dip2px(getContext(), 30 / 2) - dotPaint.measureText(" ") / 2, saleYDot - Utils.dip2px(getContext(), 15), dotPaint);
}
private void drawInnerXPaint (Canvas canvas){
// 5
//
float perHight = (mBaseHeight - mBasePaddingBottom - mBasePaddingTop) / 4;
//
canvas.drawLine(0 + mBasePaddingLeft, mBasePaddingTop,
mBaseWidth - mBasePaddingRight, mBasePaddingTop, mInnerXPaint);//
canvas.drawLine(0 + mBasePaddingLeft, mBasePaddingTop + perHight * 1,
mBaseWidth - mBasePaddingRight, mBasePaddingTop + perHight * 1, mInnerXPaint);//2
canvas.drawLine(0 + mBasePaddingLeft, mBasePaddingTop + perHight * 2,
mBaseWidth - mBasePaddingRight, mBasePaddingTop + perHight * 2, mInnerXPaint);//3
canvas.drawLine(0 + mBasePaddingLeft, mBasePaddingTop + perHight * 3,
mBaseWidth - mBasePaddingRight, mBasePaddingTop + perHight * 3, mInnerXPaint);//4
canvas.drawLine(0 + mBasePaddingLeft, mBaseHeight - mBasePaddingBottom,
mBaseWidth - mBasePaddingRight, mBaseHeight - mBasePaddingBottom, mInnerXPaint);//
}
private void drawXYPaint (Canvas canvas){
// y
// 、
Paint.FontMetrics fontMetrics = mXYPaint.getFontMetrics();
float height = fontMetrics.descent - fontMetrics.ascent;
//draw min
float txtWigth = Utils.dip2px(getContext(), 10) + mLeftTxtPadding;
// , , 。
float perYWidth = (mBaseHeight - mBasePaddingBottom - mBasePaddingTop) / 4;
//
for (int i = 0; i < 5; i++) {
canvas.drawText((20 * i) + "",
mBasePaddingLeft - txtWigth,
mBaseHeight - mBasePaddingBottom - perYWidth * i + height / 2, mXYPaint);
}
// x
//x
float hight = mBaseHeight - mBasePaddingBottom + mBottomTxtPadding;
// X
float space = (mBaseWidth - mBasePaddingLeft - mBasePaddingRight - mXYPaint.measureText("2020-02-02") * 2 - mXYPaint.measureText("2020-02-02") / 2) / 2; //
canvas.drawText("2020-02-02", mBasePaddingLeft - mXYPaint.measureText("2020-02-02") / 2, hight, mXYPaint);
canvas.drawText("2020-02-04", mBasePaddingLeft + space + mXYPaint.measureText("2020-02-02") / 2, hight, mXYPaint);
canvas.drawText("2020-02-06", mBaseWidth - mBasePaddingRight - mXYPaint.measureText("2020-02-02"), hight, mXYPaint);
}
private void drawBrokenPaint (Canvas canvas){
mPerX = (mBaseWidth - mBasePaddingLeft - mBasePaddingRight) / mPoints.size();
mPerY = ((mBaseHeight - mBasePaddingTop - mBasePaddingBottom) / 80);
Path path = new Path();
path.moveTo(mBasePaddingLeft, (mBaseHeight - mBasePaddingTop) - (mPoints.get(0).y * mPerY));
for (int i = 1; i < mPoints.size(); i++) {
path.lineTo(mBasePaddingLeft + (i * mPerX), (mBaseHeight - mBasePaddingTop) - (mPoints.get(i).y * mPerY));
}
canvas.drawPath(path, mLinePaint);
}
public void setData (ArrayList < Point > points) {
this.mPoints = points;
invalidate();
}
githubアドレスはhttps://github.com/yybDream/ChartView/tree/master