对于Android折线图,我做了许多,滑动的,不可滑动的,点击弹框的等等,在这里跟大家分享下今天刚写的一个不可滑动的折线图
首先说下大概思路:
CoordinateBase 作为一个基类,只负责点坐标的运算;LineView 这个类继承自CoordinateBase,主要负责根据点的坐标去绘制canvas。
直接上源码,代码不难,看看就会了,大家如果有问题可以留言,发现bug更好,在这里先感谢大家。
CoordinateBase.java
public abstract class CoordinateBase extends View {
private final Boolean isLog = false;
private Context context;
protected Rect mRect = new Rect(0, 0, 720, 1280);
private float ratioX, ratioY;
private ArrayList
private int maxValue = 250, minValue = 0;
private float xTemp, yTemp;
private float xAreaHeight;
protected float density;
private float marginLength;
private Boolean displaySelectLine = false;
private float xInterval;
private float pointSize;
private int lastSelectPosition = -1;
public CoordinateBase(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initParams(context);
}
public CoordinateBase(Context context, AttributeSet attrs) {
super(context, attrs);
initParams(context);
}
public CoordinateBase(Context context) {
super(context);
initParams(context);
}
private void initParams(Context context) {
this.context = context;
this.density = context.getResources().getDisplayMetrics().density;
int[] params = extremeSetting();
if (params != null && params.length == 2) {
minValue = params[0];
maxValue = params[1];
}
if (isLog) {
Log.i("Jiaqi", "minValue = " + minValue);
Log.i("Jiaqi", "maxValue = " + maxValue);
}
this.setClickable(true);
this.setOnTouchListener(mOnTouchListener);
}
protected abstract int[] extremeSetting();
protected abstract float xAreaHeightSetting();
protected abstract float marginLengthSetting();
protected abstract ArrayList
protected abstract void drawLine(Canvas canvas, float ratioX, float ratioY);
protected abstract void drawAreas(Canvas canvas, float ratioX, float ratioY);
protected abstract void drawSelectLine(Canvas canvas, float ratioX, float ratioY,int selectPosition);
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (isLog) {
Log.i("Jiaqi", "onMeasure");
}
xAreaHeight = xAreaHeightSetting();
marginLength = marginLengthSetting();
ratioX = this.getMeasuredWidth() * 1f / 720;
ratioY = this.getMeasuredHeight() * 1f / 1280;
pointArr = dataInput();
if (pointArr != null) {
for (int i = 0; i < pointArr.size(); i++) {
if (pointArr.get(i) != null && pointArr.get(i).size() > 0) {
calculateXY(pointArr.get(i));
}
}
}
if (isLog) {
Log.i("Jiaqi", "Calculating Over");
}
}
private void calculateXY(ArrayList
pointSize = pointArr.get(0).getSize();
xInterval = (720 * ratioX - 2 * pointSize - marginLength * 2) / (pointArr.size() - 1);
float yInterval = (1280 * ratioY - pointSize - xAreaHeight) / (maxValue - minValue);
if (isLog) {
Log.i("Jiaqi", "xAreaHeight = " + xAreaHeight);
}
for (int i = 0; i < pointArr.size(); i++) {
xTemp = marginLength + pointSize + i * xInterval;
yTemp = 1280 * ratioY - xAreaHeight - yInterval * pointArr.get(i).getyValue();
pointArr.get(i).setX(xTemp);
pointArr.get(i).setY(yTemp);
}
}
private void searchSelectPosition(float touchX)
{
int position = -1;
if(pointArr!=null&&pointArr.size()>0){
position = (int) ((touchX - pointSize - marginLength - xInterval/2)/xInterval);
for(int i = 0;i<pointArr.size();i++){
if(position>=pointArr.get(i).size()){
position = -1;
break;
}
}
}
if(position>=0&&lastSelectPosition!=position){
invalidate();
}
lastSelectPosition = position;
}
private OnTouchListener mOnTouchListener = new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
displaySelectLine = true;
searchSelectPosition(event.getX());
break;
case MotionEvent.ACTION_MOVE:
searchSelectPosition(event.getX());
break;
case MotionEvent.ACTION_UP:
displaySelectLine = false;
invalidate();
break;
default:
break;
}
return false;
}
};
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (isLog) {
Log.i("Jiaqi", "onDraw");
}
drawAreas(canvas, ratioX, ratioY);
drawLine(canvas, ratioX, ratioY);
if(displaySelectLine){
if(lastSelectPosition>=0){
drawSelectLine(canvas, ratioX, ratioY, lastSelectPosition);
}
}
}
public void setDisplaySelectLine(Boolean displaySelectLine) {
this.displaySelectLine = displaySelectLine;
}
public Boolean getDisplaySelectLine() {
return displaySelectLine;
}
}
LineView.java
public class LineView extends CoordinateBase {
/**样式相关参数,可修改**/
private final int maxValue = 300;
private final int minValue = 0;
private float areasHeight;
private float textSize;
private int[] lineColors = null;
/**其余参数,请勿修改**/
private final Boolean isLog = false;
private Context context;
private ArrayList
private DataEnterListener mDataListener = null;
private SelectListener mSelectListener = null;
private Paint coorPaint = null, textPaint = null, linePaint = null, pointPaint = null;
public LineView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
/**坐标轴高度 坐标文字大小**/
this.areasHeight = 50 * density;
this.textSize = 11*density;
initPaint();
}
private void initPaint() {
this.coorPaint = new Paint();
this.coorPaint.setAntiAlias(true);
this.coorPaint.setColor(0xff999999);
this.coorPaint.setStrokeWidth(0.5f * density);
this.coorPaint.setAlpha(255);
this.coorPaint.setStyle(Paint.Style.FILL_AND_STROKE);
this.textPaint = new Paint();
this.textPaint.setAntiAlias(true);
this.textPaint.setColor(0xff999999);
this.textPaint.setAlpha(255);
this.textPaint.setStyle(Paint.Style.FILL_AND_STROKE);
this.textPaint.setTypeface(Typeface.DEFAULT);
this.textPaint.setTextSize(textSize);
this.textPaint.setTextAlign(Align.CENTER);
this.linePaint = new Paint();
this.linePaint.setAntiAlias(true);
this.linePaint.setColor(0xff999999);
this.linePaint.setStrokeWidth(1f * density);
this.linePaint.setAlpha(255);
this.linePaint.setStyle(Paint.Style.FILL_AND_STROKE);
this.pointPaint = new Paint();
this.pointPaint.setAntiAlias(true);
this.pointPaint.setColor(0xff999999);
this.pointPaint.setStrokeWidth(0f);
this.pointPaint.setAlpha(255);
this.pointPaint.setStyle(Paint.Style.FILL);
}
public void setPaintColor(int coorColor, int[] lineColors) {
this.coorPaint.setColor(coorColor);
this.textPaint.setColor(coorColor);
this.lineColors = lineColors;
invalidate();
}
@Override
protected int[] extremeSetting() {
int[] extreme = new int[2];
extreme[0] = minValue;// minValue
extreme[1] = maxValue;// maxValue
return extreme;
}
@Override
protected float xAreaHeightSetting() {
return areasHeight;
}
@Override
protected float marginLengthSetting() {
return 20*density;
}
@Override
protected ArrayList
data = null;
if (mDataListener != null) {
data = mDataListener.setData();
}
return data;
}
@Override
protected void drawLine(Canvas canvas, float ratioX, float ratioY) {
if (data != null) {
for (int index = 0; index < data.size(); index++) {
ArrayList
if (lineColors != null && index < lineColors.length) {
linePaint.setColor(lineColors[index]);
}
for (int i = 0; i < dataItem.size() - 1; i++) {
/** drawLine **/
canvas.drawLine(dataItem.get(i).getX(), dataItem.get(i).getY(), dataItem.get(i + 1).getX(), dataItem.get(i + 1).getY(), linePaint);
pointPaint.setColor(dataItem.get(i).getPointColor());
/** drawPoint **/
canvas.drawCircle(dataItem.get(i).getX(), dataItem.get(i).getY(), dataItem.get(i).getSize(), pointPaint);
}
/**the last one point**/
pointPaint.setColor(dataItem.get(dataItem.size() - 1).getPointColor());
canvas.drawCircle(dataItem.get(dataItem.size() - 1).getX(), dataItem.get(dataItem.size() - 1).getY(), dataItem.get(dataItem.size() - 1).getSize(), pointPaint);
}
}
}
@Override
protected void drawAreas(Canvas canvas, float ratioX, float ratioY) {
if (areasHeight > 0) {
if (isLog) {
Log.i("Jiaqi", "LineView->mRect.width = " + mRect.width());
Log.i("Jiaqi", "LineView->mRect.height = " + mRect.height());
Log.i("Jiaqi", "LineView->ratioX = " + ratioX);
Log.i("Jiaqi", "LineView->ratioY = " + ratioY);
}
canvas.drawLine(0f, mRect.height() * ratioY - areasHeight, mRect.width() * ratioX, mRect.height() * ratioY - areasHeight, coorPaint);
if(data.size()>0){
ArrayList
if(dataItem!=null){
for(int i = 0;i<dataItem.size();i++){
canvas.drawText(dataItem.get(i).getxValue(), dataItem.get(i).getX(), mRect.height() * ratioY - areasHeight + textSize*3/2, textPaint);
}
}
}
}
}
@Override
protected void drawSelectLine(Canvas canvas, float ratioX, float ratioY, int selectPosition) {
canvas.drawLine(data.get(0).get(selectPosition).getX(), 0, data.get(0).get(selectPosition).getX(), 1280*ratioY-areasHeight, coorPaint);
if(mSelectListener!=null){
mSelectListener.getPosition(selectPosition);
}
}
/**接口**/
public interface DataEnterListener {
public ArrayList
}
public void setDataEnterListener(DataEnterListener mListener) {
this.mDataListener = mListener;
}
public interface SelectListener{
public void getPosition(int position);
}
public void setSelectListener(SelectListener mListener)
{
this.mSelectListener = mListener;
}
}
public class MainActivity extends Activity {
private ArrayList
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
InitViews();
}
private void InitViews() {
/** 每个dataItem中的CoorPoint数量一定要一样!!!**/
ArrayList
for (int i = 0; i < 20; i++) {
dataItem.add(new CoorPoint(8, i + "", (int) (100 + 50 * Math
.random()), 0xffff0000, true));
}
data.add(dataItem);
dataItem = new ArrayList
for (int i = 0; i < 20; i++) {
dataItem.add(new CoorPoint(8, i + "", (int) (200 + 50 * Math
.random()), 0xff0000ff, true));
}
data.add(dataItem);
LineView line = (LineView) findViewById(R.id.lineview);
line.setPaintColor(0xff999999, new int[] { 0xffff0000, 0xff0000ff });
line.setDataEnterListener(new DataEnterListener() {
@Override
public ArrayList
return data;
}
});
line.setSelectListener(new SelectListener() {
@Override
public void getPosition(int position) {
Log.i("XiaoHuai", "selectPosition = " + position);
}
});
}
}