MPAndroidChart是Android平臺上一款強大易用的圖表庫,支持線狀圖、柱狀圖、散點圖等八種圖表類型和縮放、拖動(平移)、選擇等手勢,還支持動畫和高亮等功能。但是別人給好的功能畢竟只能滿足一般功能,一個程序員最基本的能力就應該是根據需求做出自定義的功能了,這裏我對MPAndroidChart進行一些改造,MPAndroidChart只能在節點繪製圓形,現在要給它加上繪製叉號的功能。另外,本來MPAndroidChart的背景只能設置整個一大塊背景,現在我加上了按行設置背景色的功能。
效果如圖:
節點的細節部分:
功能實現
繼承LineChart
自定義LineChart的第一步是要繼承LineChart,實現其構造方法。然後重寫onDraw方法,在onDraw方法中,再繪製背景,繪製叉號,繪製圖表。這裏要注意繪製的順序,從下到上,一層層疊加。
/**
* 重寫onDraw方法,注意繪製順序,先繪製背景色,再繪製叉號,最後繪製圖表
* @param canvas
*/
@Override
protected void onDraw(Canvas canvas) {
drawBgColor(canvas);
drawCross(canvas);
super.onDraw(canvas);
Log.i(TAG, "onDraw");
}
畫背景
爲了讓代碼看起來更直觀,我先創建了一個類BgColor,其中包含start,stop和color三個屬性。
/**
* Created by xiaoniu on 2017/4/10.
* BgColor是設置背景的單位,創建時需要傳入起點和終點的值,還有要設置的顏色
* 如要把縱座標20-40的背景設爲紅色,就新建一個BgColor
* new BgColor(20,40,Color.RED)
*/
public class BgColor {
/**
* @param start 起始點
* @param stop 結束點
* @param color 顏色
*/
public BgColor( float start, float stop,int color) {
this.start = stop;
this.stop = start;
this.color = color;
}
private float start;
private float stop;
private int color;
public float getStart() {
return start;
}
public void setStart(float start) {
this.start = start;
}
public float getStop() {
return stop;
}
public void setStop(float stop) {
this.stop = stop;
}
public int getColor() {
return color;
}
public void setColor(int color) {
this.color = color;
}
}
三個屬性分別對應起始點,結束點和顏色。然後將自己需要設置的背景都放到一個List中。
/**
* 分段背景設置
* @return 每條背景的組合
*/
private ArrayList<BgColor> getBg() {
ArrayList<BgColor> bgList = new ArrayList<>();
bgList.add(new BgColor(10, 20, Color.YELLOW));//參數信息:縱座標從0到20設置顏色爲黃色
bgList.add(new BgColor(20, 40, 0xFF00FF00));//支持16進制顏色
bgList.add(new BgColor(40, 70, Color.BLUE));
bgList.add(new BgColor(70, 80, Color.RED));
return bgList;
}
別忘了給圖表設置繪製背景的屬性,之後再把數據傳給圖表。
//給表格背景添加顏色
mChart.setDrawBgColor(true);
//設置背景顏色的屬性
mChart.setBgColor(getBg());
而在自定義LineChart的drawBgColor方法中,就是從List中取出每個BgColor,獲得其start和stop,再根據MPAndroidChart提供的能夠將圖表上的值轉換爲像素座標點的方法getPixelForValues,得到需要繪製背景的左下角和右上角的座標,用canvas畫矩形就可以了。
private void drawBgColor(Canvas canvas) {
if (enableDrawBgColor) {
if (!bgList.isEmpty()) {
Paint paint = new Paint();
for (BgColor r : bgList
) {
MPPointD pStart = this.getPixelForValues(this.getXChartMin(), r.getStart(), YAxis.AxisDependency.LEFT);//左下角
MPPointD pStop = this.getPixelForValues(this.getXChartMax(), r.getStop(), YAxis.AxisDependency.LEFT);//右上角
paint.setColor(r.getColor());
canvas.drawRect(new RectF((float) pStart.x, (float) pStart.y, (float) pStop.x, (float) pStop.y), paint);
}
}else {
Log.i(TAG, "No BgColor to Draw");
}
}
}
畫叉號
畫叉號之前要得到節點的數據,同樣是利用getPixelForValues將圖表上的值轉化爲像素座標點
private void drawCross(Canvas canvas) {
if (enableDrawCross) {
if (this.getData() != null) {
LineDataSet set = (LineDataSet) this.getData().getDataSetByIndex(0);
list = set.getValues();
set.setDrawCircles(false);
LineData data = new LineData(set);
this.setData(data);
for (Entry e : list
) {
MPPointD p = this.getPixelForValues(e.getX(), e.getY(), YAxis.AxisDependency.LEFT);
drawNode(canvas, (float) p.x, (float) p.y);
}
}else{
Log.i(TAG, "No Data to Draw");
}
}
}
畫叉號就是繪製兩個互相垂直的直線,有了像素座標點和canvas也就很簡單了。
private void drawNode(Canvas canvas, float x, float y) {
Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setStrokeWidth(crossWidth);
canvas.drawLine(x - crossLength / 2, y - crossLength / 2, x + crossLength / 2, y + crossLength / 2, paint);
canvas.drawLine(x - crossLength / 2, y + crossLength / 2, x + crossLength / 2, y - crossLength / 2, paint);
}
END
細節比較粗糙,以後再完善,歡迎評論交流。
最後附上github代碼:https://github.com/xiaoniu/CrossNodeLineChart