效果图:
实现源码:
/** * FunctionCurveView.java * @author Lanfog * @datetime a01b-6-ab下午b:38:01 */ package me.lanfog.myandroid.widget; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.util.AttributeSet; import android.view.View; /** * 函数曲线图 */ public class CurveView extends View { private Paint mPaint; private CurveUnit mCurveUnit = new CurveUnit() { @Override public int getCenterY() { // TODO Auto-generated method stub return getHeight()/2; } @Override public int getCenterX() { // TODO Auto-generated method stub return getWidth()/2; } @Override public float function(float x) { // TODO Auto-generated method stub return (float) Math.sin(x); } }; public CurveView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); // TODO Auto-generated constructor stub init(); } public CurveView(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub init(); } public CurveView(Context context) { super(context); // TODO Auto-generated constructor stub init(); } private void init(){ mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setStyle(Paint.Style.STROKE); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int measuredWidth = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec); int measuredHeight = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec); setMeasuredDimension(measuredWidth, measuredHeight); } @Override protected void onDraw(Canvas canvas) { int w = getWidth(); // 控件宽度 int h = getHeight(); // 控件高度 int p = mCurveUnit.getPadding(); // 控件内部填充 int cx = mCurveUnit.getCenterX(); // 中心横坐标 int cy = mCurveUnit.getCenterY(); // 中心纵坐标 mPaint.setStrokeWidth(2); canvas.drawLine(p, cy, w - p, cy, mPaint); canvas.drawLine(cx, p, cx, h - p, mPaint); float pr = mCurveUnit.getPrecision(); // 刻度精度 float sp = mCurveUnit.getSpacing(); // 刻度间隔 float x, y; mPaint.setStrokeWidth(1); mPaint.setTextSize(12); int a = 3; // 短线刻度长度 int b = 8; // 长线刻度长度 // 中 canvas.drawText("0", cx + 15, cy + 15, mPaint); // 左 for(int i=-1;;i--){ x = cx + i * sp; if(x < p) break; if(i % 5 == 0){ // 每5个刻度绘制一个数字 canvas.drawLine(x, cy, x, cy - b, mPaint); canvas.drawText("" + i * pr, x, cy + 15, mPaint); }else canvas.drawLine(x, cy, x, cy - a, mPaint); } // 上 for(int i=1;;i++){ y = cy - i * sp; if(y < p) break; if(i % 5 == 0){ canvas.drawLine(cx, y, cx + b, y, mPaint); canvas.drawText("" + i * pr, cx + 10, y, mPaint); }else canvas.drawLine(cx, y, cx + a, y, mPaint); } // 右 for(int i=1;;i++){ x = cx + i * sp; if(x > w - p) break; if(i % 5 == 0){ canvas.drawLine(x, cy, x, cy - b, mPaint); canvas.drawText("" + i * pr, x, cy - 10, mPaint); }else canvas.drawLine(x, cy, x, cy - a, mPaint); } // 下 for(int i=-1;;i--){ y = cy - i * sp; if(y > h - p) break; if(i % 5 == 0){ canvas.drawLine(cx, y, cx + b, y, mPaint); canvas.drawText("" + i * pr, cx + 10, y, mPaint); }else canvas.drawLine(cx, y, cx + a, y, mPaint); } mPaint.setColor(Color.RED); boolean s = false; // 是否为起始点 float tx, ty; // 临时保存坐标点 float lx = 0f, ly = 0f; // 上一次保存坐标点 // 负 for(int i=0;;i--){ if(cx + i * sp < p) break; tx = x = i * pr; ty = y = mCurveUnit.function(x); x = cx + i * sp; y = cy - y / pr * sp; if(i % 10 == 0) // 每10个刻度绘制一个(x,y)值 canvas.drawText("(" + String.format("%.2f", tx) + "," + String.format("%.2f", ty) + ")", x, y, mPaint); if(s) canvas.drawLine(lx, ly, x, y, mPaint); else s = true; lx = x; ly = y; } s = false; // 正 for(int i=0;;i++){ if(cx + i * sp > w - p) break; tx = x = i * pr; ty = y = mCurveUnit.function(x); x = cx + i * sp; y = cy - y / pr * sp; if(i % 10 == 0) canvas.drawText("(" + String.format("%.2f", tx) + "," + String.format("%.2f", ty) + ")", x, y, mPaint); if(s) canvas.drawLine(lx, ly, x, y, mPaint); else s = true; lx = x; ly = y; } } public static abstract class CurveUnit { /** * 函数实现 */ public abstract float function(float x); /** * 获取中心的水平位置 */ public abstract int getCenterX(); /** * 获取中心的垂直位置 */ public abstract int getCenterY(); /** * 获取刻度精度 */ public float getPrecision(){ return 0.2f; } /** * 获取刻度间隔 */ public float getSpacing(){ return 10f; } /** * 获取内部填充 */ public int getPadding(){ return 5; } } public CurveUnit getCurveUnit() { return mCurveUnit; } public void setCurveUnit(CurveUnit mCurveUnit) { this.mCurveUnit = mCurveUnit; } }