您的位置:首页 > 移动开发 > Android开发

Android 上自定义的复式折线图(三)

2016-06-30 18:21 471 查看

Android 上自定义的复式折线图(一)

Android 上自定义的复式折线图(二)

有兴趣的话可以看下前面两篇文章,这几天也对其做了很多处理,尽量将其做的更加完美

这次修改也主要是为了然Y轴不动,表格可以进行水平滚动

其中做了以下支持:

设置左边控件的宽度
设置两个控件父控件的宽度
X,Y字体跟表格的距离
设置XY轴的颜色
X,Y字体颜色跟大小
表格颜色
是否显示表格
是否显示虚线
设置XY轴的文字标签
设置数据组

设置数据颜色组

效果图如下:注意第一张是表格来的,做图有问题









图一主要的实现原理:

把其弄成两个控件即左右两个,右边的用HorizontalScrollView包着,这样就可以实现水平滚动了,然后在弄个LinerLayout包着左右两个控件就OK了

首先定义一个LineViewUtil把其两个控件绑定在一起

一丶定义LineViewUtil工具类

import android.app.Activity;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;

import java.util.ArrayList;

/**
* Created by shaolin on 6/30/16.
*/
public class LineViewUtil {

private static LineViewUtil mInstances;
private Activity mContext;

private LinearLayout mLayout; //父元素
private LeftView mLeftView;
private RightView mRightView;
private HorizontalScrollView mScroll;

public static synchronized LineViewUtil getInstance() {
if (mInstances == null) {
mInstances = new LineViewUtil();
}
return mInstances;
}

public LineViewUtil() {

}

public LinearLayout getView() {
return mLayout;
}

public void setView(Activity context) {
mContext = context;
mScroll = new HorizontalScrollView(mContext);
mScroll.setHorizontalScrollBarEnabled(false);
mLayout = new LinearLayout(mContext);
mLeftView = new LeftView(mContext);
mRightView = new RightView(mContext);

mScroll.addView(mRightView);
mLayout.addView(mLeftView);
mLayout.addView(mScroll);
}

//设置左边控件的宽度
public void setLeftViewWidth(int leftViewWidth) {
mLeftView.setWidth(leftViewWidth);
mRightView.setLeftViewWidth(leftViewWidth);
}

//设置两个控件父控件的宽度
public void setWidth(int partentWidth) {
mLeftView.setPartentWidth(partentWidth);
mRightView.setPartentWidth(partentWidth);
}

//X轴字体跟表格的距离
public void setXTextToLine(int textToLine) {
mRightView.setTextToLine(textToLine);
}

//Y轴字体跟表格的距离
public void setYTextToLine(int textToLine) {
mLeftView.setTextToLine(textToLine);
}

//设置XY轴的颜色
public void setXYColor(int XYColor) {
mLeftView.setXYColor(XYColor);
mRightView.setXYColor(XYColor);
}

public void setXTextColor(int XTextColor) {
mRightView.setXTextColor(XTextColor);
}

public void setYTextColor(int YTextColor) {
mLeftView.setYTextColor(YTextColor);
}

//如果是多条数据图这里是数据的默认颜色,即没有设置数据颜色组时会起作用
public void setDefDataColor(int dataColor) {
mRightView.setDefDataColor(dataColor);
}

public void setXTextSize(int XTextSize) {
mRightView.setXTextSize(XTextSize);
}

public void setYTextSize(int YTextSize) {
mLeftView.setYTextSize(YTextSize);
}

public void setGridColor(int gridColor) {
mRightView.setGridColor(gridColor);
}

//是否虚线
public void setShowDashed(boolean isDottedLine) {
mRightView.setShowDashed(isDottedLine);
}

public void setShowGrid(boolean isShowGrid) {
mLeftView.setShowGrid(isShowGrid);
mRightView.setShowGrid(isShowGrid);
}

//设置XY轴的文字标签
public void setXYLabel(ArrayList<String> xlabel, ArrayList<String> ylabel) {
mLeftView.setYLabel(ylabel);
mRightView.setXYLabel(xlabel, ylabel);
}

//设置数据组
public void setDataList(ArrayList<ArrayList<Integer>> dataLists) {
mRightView.setDataList(dataLists);
}

//设置数据颜色组
public void setDataColorList(ArrayList<Integer> dataColorList) {
mRightView.setDataColorList(dataColorList);
}

}
二丶左边的Y轴标签控件LeftView

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;

import java.util.ArrayList;

/**
* Created by shaolin on 6/28/16.
*/
public class LeftView extends View {

private static final String TAG = "LeftView";

private int Xscale;
private int Yscale;
private int Xpoint;
private int Ypoint;

// Y轴上面的显示文字
private ArrayList<String> YLabel;
private int YTextSize = 8;
private int YTextColor = Color.WHITE;

private int defXCount = 10;
private int width = 40;
private int height;
private int partentWidth;
private int textToLine;

private int XYColor = Color.WHITE;
//是否显示表格
private boolean isGrid = false;

public LeftView(Context context) {
this(context, null);
}

public LeftView(Context context, AttributeSet attrs) {
super(context, attrs);
initSize();
}

private void initSize() {
YLabel = new ArrayList<>();
setYTextSize(YTextSize);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Xscale = (partentWidth - width * 2) / defXCount;
Yscale = Xscale / 2;

height = Yscale * YLabel.size() + Yscale;

Xpoint = width;
Ypoint = Yscale * YLabel.size();
Log.e(TAG, "width:" + width + "  ;height:" + height);
setMeasuredDimension(width, height);
}

@Override
protected void onDraw(Canvas canvas) {
Paint p1 = new Paint();
p1.setStyle(Paint.Style.STROKE);
p1.setAntiAlias(true);
p1.setColor(XYColor);
p1.setStrokeWidth(2);
drawYText(canvas);
if (!isGrid) {
drawYLine(canvas, p1);
}
}

private void drawYText(Canvas canvas) {
Paint p = new Paint();
p.setAntiAlias(true);
p.setColor(YTextColor);
p.setTextSize(YTextSize);
p.setTextAlign(Paint.Align.RIGHT);
// 纵轴数据
for (int i = 0; i < YLabel.size(); i++) {
int startY = Ypoint - i * Yscale;
canvas.drawText(this.YLabel.get(i), width - 10 - textToLine, startY + Yscale / 4, p);
}
}

//画纵轴
private void drawYLine(Canvas canvas, Paint p) {
p.setColor(XYColor);
float stopX = Xpoint;
float stopY = Ypoint - Yscale * (YLabel.size() - 1);
canvas.drawLine(Xpoint, Ypoint, stopX, stopY, p);
// Y轴最后是否有箭头
canvas.drawLine(stopX, stopY, stopX - Xscale / 6, stopY + Yscale / 3, p);
//        canvas.drawLine(stopX, stopY, stopX + Xscale / 6, stopY + Yscale / 3, p);
}

public void setWidth(int width) {
this.width = width;
}

public void setTextToLine(int textToLine) {
this.textToLine = textToLine;
}

public void setYLabel(ArrayList<String> YLabel) {
this.YLabel = YLabel;
}

public void setPartentWidth(int partentWidth) {
this.partentWidth = partentWidth;
}

public void setYTextSize(int YTextSize) {
this.YTextSize = setDimensionSP(YTextSize);
}

public void setYTextColor(int YTextColor) {
this.YTextColor = YTextColor;
}

public void setXYColor(int XYColor) {
this.XYColor = XYColor;
}

public void setShowGrid(boolean isGrid) {
this.isGrid = isGrid;
}

public int setDimensionDIP(int size) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, size,
Resources.getSystem().getDisplayMetrics());
}

public int setDimensionSP(int size) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, size,
Resources.getSystem().getDisplayMetrics());
}
}
三丶Y轴右边的表格等数据RightView控件

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathEffect;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;

import java.util.ArrayList;

/**
* Created by shaolin on 6/28/16.
*/
public class RightView extends View {

private static final String TAG = "RightView";

// 原点坐标
private int Xpoint;
private int Ypoint;

// X,Y轴的单位长度,即表格中的正方形的宽高
private int Yscale;
private int Xscale;

//是否显示表格
private boolean isGrid = false;
//是否展示表格为虚线
private boolean isDashed = false;

// X最左边跟Y左下面的线的颜色
private int XYColor = Color.WHITE;
// X轴字体的颜色
private int XTextColor = Color.WHITE;
// 表格字体的颜色
private int GridColor = Color.WHITE;
// 数据字体的颜色
private int defDataColor = Color.WHITE;

private int XTextSize = 8;

// X轴上面的显示文字
private ArrayList<String> XLabel;
// Y轴上面的显示文字
private ArrayList<String> YLabel;
// 曲线数据
private ArrayList<ArrayList<Integer>> dataLists;
private ArrayList<Integer> dataColorList;
// 单前数据
private ArrayList<Integer> dataList;
private int color;

private int defXCount = 10;
private int dataCount;

private int width;
private int height;
private int partentWidth;

private int leftViewWidth = 40;
private int textToLine;

public RightView(Context context) {
this(context, null);
}

public RightView(Context context, AttributeSet attrs) {
super(context, attrs);
initSize();
}

private void initSize() {
XLabel = new ArrayList<>();
YLabel = new ArrayList<>();
dataColorList = new ArrayList<>();
dataList = new ArrayList<>();
dataLists = new ArrayList<>();
setXTextSize(XTextSize);
}

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (dataLists.size() > 0 && partentWidth > 0) {
Xscale = (partentWidth - leftViewWidth * 2) / defXCount;
Yscale = Xscale / 2;
if (dataLists.get(0).size() <= defXCount) {
dataCount = defXCount;
} else {
dataCount = dataLists.get(0).size();
}
}

width = Xscale * dataCount + leftViewWidth;
height = Yscale * YLabel.size() + Yscale + XTextSize;

Xpoint = 0;
Ypoint = Yscale * YLabel.size();
Log.e(TAG, "width:" + width + " ;height:" + height);
setMeasuredDimension(width, height);
}

@Override
protected void onDraw(Canvas canvas) {
Paint p1 = new Paint();
p1.setStyle(Paint.Style.STROKE);
p1.setAntiAlias(true);
p1.setColor(XYColor);
p1.setStrokeWidth(2);
if (isGrid) {
this.drawTable(canvas);
} else {
this.drawXLine(canvas, p1);
this.drawYLine(canvas, p1);
}
if (dataLists != null) {
for (int i = 0; i < dataLists.size(); i++) {
this.drawData(canvas, i);
}
}
}

// 画表格
private void drawTable(Canvas canvas) {
Paint paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setColor(GridColor);
Path path = new Path();
if (isDashed) {
PathEffect effects = new DashPathEffect(new float[]{5, 5, 5, 5}, 1);//画虚线
paint.setPathEffect(effects);
}
int startX = 0;
int startY = 0;
int stopX = 0;
int stopY = 0;
// 纵向线
for (int i = 0; i <= dataCount; i++) {
startX = Xpoint + i * Xscale;
startY = Ypoint;
stopY = Ypoint - (this.YLabel.size() - 1) * Yscale;
if (i != 0) {
path.moveTo(startX - Xscale / 2, startY);
path.lineTo(startX - Xscale / 2, stopY);
canvas.drawPath(path, paint);
}
path.moveTo(startX, startY);
path.lineTo(startX, stopY);
canvas.drawPath(path, paint);
}

// 横向线
for (int i = 0; i < YLabel.size(); i++) {
startX = Xpoint;
startY = Ypoint - i * Yscale;
stopX = Xpoint + (dataCount) * Xscale;
path.moveTo(startX, startY);
path.lineTo(stopX, startY);
paint.setColor(GridColor);
canvas.drawPath(path, paint);
}
}

//画纵轴
private void drawYLine(Canvas canvas, Paint p) {
p.setColor(XYColor);
float stopX = Xpoint;
float stopY = Ypoint - Yscale * (YLabel.size() - 1);
canvas.drawLine(Xpoint, Ypoint, stopX, stopY, p);
// Y轴最后是否有箭头
//        canvas.drawLine(stopX, stopY, stopX - Xscale / 6, stopY + Yscale / 3, p);
canvas.drawLine(stopX, stopY, stopX + Xscale / 6, stopY + Yscale / 3, p);
}

// 画横轴
private void drawXLine(Canvas canvas, Paint p) {
p.setColor(XYColor);
float stopX = Xpoint + Xscale * dataCount;
float stopY = Ypoint;
canvas.drawLine(Xpoint, Ypoint, stopX, stopY, p);
// X轴最后是否有箭头
canvas.drawLine(stopX, stopY, stopX - Xscale / 6, stopY - Yscale / 3, p);
canvas.drawLine(stopX, stopY, stopX - Xscale / 6, stopY + Yscale / 3, p);
}

// 画数据
private void drawData(Canvas canvas, int pos) {
dataList = dataLists.get(pos);
if (dataColorList.size() == 0) {
color = defDataColor;
} else {
color = dataColorList.get(pos);
}

Paint p = new Paint();
p.setAntiAlias(true);

/* // 纵轴数据
for (int i = 0; i < YLabel.size(); i++) {
int startY = Ypoint - i * Yscale;
p.setColor(YTextColor);
p.setTextSize(XTextSize);
p.setTextAlign(Paint.Align.RIGHT);
canvas.drawText(this.YLabel.get(i), this.Margin / 4 * 3 + marginLeft,
startY + this.Margin / 4, p);
}*/

//横轴数据
for (int i = 0; i < dataCount; i++) {
int startX = Xpoint + i * Xscale;
p.setColor(XTextColor);
p.setTextSize(XTextSize);
p.setTextAlign(Paint.Align.CENTER);
String text = "";
if (i < XLabel.size()) {
text = this.XLabel.get(i);
}
canvas.drawText(text, startX + Xscale / 2, Ypoint + XTextSize + 5 + textToLine, p);

p.setColor(dataColorList.size() > 0 ? color : defDataColor);
if (i < XLabel.size()) {
canvas.drawCircle(startX + Xscale / 2, calY(dataList.get(i)), 4, p);
}
if (i < XLabel.size() - 1) {
canvas.drawLine(startX + Xscale / 2, calY(dataList.get(i)),
Xpoint + (i + 1) * Xscale + Xscale / 2, calY(dataList.get(i + 1)), p);
}
}
}

private int calY(int y) {
int y0 = 0;
int y1 = 0;
try {
y0 = Integer.parseInt(YLabel.get(0));
y1 = Integer.parseInt(YLabel.get(1));
} catch (Exception e) {
return 0;
}
try {
return Ypoint - ((y - y0) * Yscale / (y1 - y0));
} catch (Exception e) {
return 0;
}
}

public void setLeftViewWidth(int leftViewWidth) {
this.leftViewWidth = leftViewWidth;
}

public void setPartentWidth(int partentWidth) {
this.partentWidth = partentWidth;
}

public void setTextToLine(int textToLine) {
this.textToLine = textToLine;
}

public void setXYColor(int XYColor) {
this.XYColor = XYColor;
}

public void setXTextColor(int XTextColor) {
this.XTextColor = XTextColor;
}

public void setGridColor(int gridColor) {
this.GridColor = gridColor;
}

public void setDefDataColor(int defDataColor) {
this.defDataColor = defDataColor;
}

public void setXTextSize(int XTextSize) {
this.XTextSize = setDimensionSP(XTextSize);
}

public void setShowDashed(boolean isDashed) {
this.isDashed = isDashed;
}

public void setShowGrid(boolean isGrid) {
this.isGrid = isGrid;
}

public void setXYLabel(ArrayList<String> xlabel, ArrayList<String> ylabel) {
this.XLabel = xlabel;
this.YLabel = ylabel;
}

public void setDataList(ArrayList<ArrayList<Integer>> dataLists) {
this.dataLists = dataLists;
postInvalidate();
}

public void setDataColorList(ArrayList<Integer> dataColorList) {
this.dataColorList = dataColorList;
}

public int setDimensionDIP(int size) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, size,
Resources.getSystem().getDisplayMetrics());
}

public int setDimensionSP(int size) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, size,
Resources.getSystem().getDisplayMetrics());
}
}
四丶这里在弄个例子出来是不是就比较完美了,这就来...

MainActivity.java

public class MainActivity extends Activity {

private ArrayList<Integer> colorList = new ArrayList<>();
private ArrayList<String> XLabel = new ArrayList<>();
private ArrayList<String> YLabel = new ArrayList<>();

private LineViewUtil mUtil;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

initData();
mUtil = LineViewUtil.getInstance();
mUtil.setView(this);
mUtil.setXYLabel(XLabel, YLabel);
mUtil.setDataColorList(colorList);
mUtil.setWidth(getLineViewWidth());
mUtil.setShowGrid(true);
mUtil.setGridColor(Color.LTGRAY);
randSet(mUtil);

LinearLayout layout = (LinearLayout) findViewById(R.id.layout);
layout.addView(mUtil.getView());
}

private void initData() {
colorList.add(getResources().getColor(R.color.using_before));
colorList.add(getResources().getColor(R.color.using_after));
for (int i = 0; i < 15; i++) {
XLabel.add(String.valueOf(i + 1));
}
for (int i = 0; i < 11; i++) {
YLabel.add(String.valueOf(i * 10));
}
}

private void randSet(LineViewUtil util) {
ArrayList<ArrayList<Integer>> dataLists = new ArrayList<>();

ArrayList<Integer> dataList1 = new ArrayList<Integer>();
int random1 = (int) (Math.random() * 99 + 1);
for (int i = 0; i < XLabel.size(); i++) {
dataList1.add((int) (Math.random() * random1));
}

ArrayList<Integer> dataList2 = new ArrayList<Integer>();
int random2 = (int) (Math.random() * 99 + 1);
for (int i = 0; i < XLabel.size(); i++) {
dataList2.add((int) (Math.random() * random2));
}
dataLists.add(dataList1);
dataLists.add(dataList2);
util.setDataList(dataLists);
}

private int getLineViewWidth() {
return getWindowManager().getDefaultDisplay().getWidth();
}
}
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#55000000"
android:orientation="vertical">

<LinearLayout
android:id="@+id/layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" />

</LinearLayout>
colors.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="using_before">#f6e749</color>
<color name="using_after">#7ae6fe</color>
</resources>

Demo:http://download.csdn.net/detail/qq_30552993/9564198
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: