笑談Android圖表-MPAndroidChart


MPAndroidChart是一款基於Android的開源圖表庫,MPAndroidChart不僅可以在Android設備上繪制各種統計圖表,而且可以對圖表進行拖動和縮放操作,應用起來非常靈活。MPAndroidChart顯得更為輕巧和簡單,擁有常用的圖表類型:線型圖、餅圖、柱狀圖和散點圖。


MPAndroidCharts GitHub地址鏈接

項目地址鏈接(改成了github)

歡迎大家吐槽,小弟初來炸到,這是本人寫的第一篇博客,希望大家多提意見,不勝感激

圖表效果圖

  • LineChart

    • 這里寫圖片描述
  • BarChart


    • BarChart

    • HorizontalBarChart

    • 這里寫圖片描述
  • PieChart


    • 這里寫圖片描述
  • RadarChart

    • 這里寫圖片描述

圖表常用功能及方法介紹:

  • XY軸的繪制

    • setEnabled(boolean enabled):設置軸是否被繪制。默認繪制,false不會被繪制。
    • setDrawLabels(boolean enabled):設置為true打開繪制軸的標簽。
    • setDrawAxisLine(boolean enabled): 設置為true,繪制軸線
    • setDrawGridLines(boolean enabled): 設置為true繪制網格線。
  • 定義軸線樣式

    • setTextColor(int color): 設置軸標簽文本顏色。
    • setTextSize(float size):設置軸標簽的字體大小。
    • setTypeface(Typeface tf):設置軸標簽的自定義Typeface(Typeface.createFromAsset(getAssets(), "字體文件名");)
    • setGridColor(int color): 設置網格線顏色。
    • setGridLineWidth(float width):設置網格線寬度。
    • setAxisLineColor(int color):設置此軸的坐標軸的顏色。
    • setAxisLineWidth(float width): 設置此軸的坐標軸的寬度。
    • setVisibleXRangeMaximum(float maxXRange):設置x軸最多顯示數據條數,(要在設置數據源后調用,否則是無效的)
    • enableGridDashedLine(float lineLength, float spaceLength, float phase): 顯示網格線虛線模式,"lineLength"控制短線條的長度,"spaceLength"控制兩段線之間的間隔長度,"phase"控制開始的點。
  • 圖表交互設置

    • setTouchEnabled(boolean enabled): 允許你打開或者關閉與圖表的所有觸摸交互的情況。
    • setDragEnabled(boolean enabled): 打開或關閉對圖表的拖動。
    • setScaleEnabled(boolean enabled):打開或關閉對圖表所有軸的的縮放。
    • setScaleXEnabled(boolean enabled): 打開或關閉x軸的縮放
    • setScaleYEnabled(boolean enabled): 打開或關閉y軸的縮放。
    • setPinchZoom(boolean enabled): 如果設置為true,擠壓縮放被打開。如果設置為false,x和y軸可以被單獨擠壓縮放。
    • setHighlightEnabled(boolean enabled): 如果設置為true,在圖表中選中觸屏高亮。
    • setHighlightPerDragEnabled(boolean enabled): 設置為true時允許高亮顯示拖動結束的對象在縮放到最下時。默認:true
    • setHighlightIndicatorEnabled(boolean enabled): 如果設置為true, 指標線(或桿)將展示被選擇的線的繪制的值。
  • 自定義軸線的值
    • setAdjustXLabels(boolean enabled):如果被設置為true,x軸條目將依賴於它自己在進行縮放的時候。如果設置為false,x軸條目將總是保持相同。
    • setAvoidFirstLastClipping(boolean enabled):如果設置為true,圖表將避免第一個和最后一個標簽條目被減掉在圖表或屏幕的邊緣。
    • setSpaceBetweenLabels(int characters): 設置x軸標簽之間的空間字符數,默認是4個。
    • setPosition(XAxisPosition pos):設置XAxis應該出現的位置。可以選擇TOP,BOTTOM,BOTH_SIDED,TOP_INSIDE或者BOTTOM_INSIDE。
    • setStartAtZero(boolean enabled):如果這個打開,軸線總是有最小值0,無論什么類型的圖表被展示。
    • setAxisMaxValue(float max):設置一個自定義的最大值為這條軸,如果設置了,這個值將不會依賴於提供的數據自動計算。
    • resetAxisMaxValue(): 調用這個將撤銷以前設置的最大值。這意味着,你將再次允許軸自動計算它的最大值。
    • setAxisMinValue(float min): 設置一個自定義的最小值。如果設置了,這個值將不會依賴於你提供的數據進行自動計算。
    • resetAxisMinValue():調用這個方法撤銷以前設置的最小值。這意味着,你將再次允許軸自動計算他的最小值。
    • setInverted(boolean enabled): 如果設置為true,這個軸將被反向,那意味着最高出的將到底部,最低部的到頂端。
    • setSpaceTop(float percent):設置在圖表上最高處的值相比軸上最高值的頂端空間(總軸范圍的百分比)
    • setSpaceBottom(float percent): 設置在圖表上最低處的值相比軸上最低處值的底部空間(總軸范圍的百分比)
    • setShowOnlyMinMax(boolean enabled): 如果打開了,這個軸將展示出它的最小值和最大值。這將忽略或者覆蓋定義過的label-count。
    • setPosition(YAxisLabelPosition pos):設置軸標簽應該被繪制的位置。INSIDE_CHART或者OUTSIDE_CHART中的一個。 自定義影響軸的數值范圍應該在圖表被設置數據之前應用。

創建圖表(LineChart舉例)

  • 布局文件: activity_barchart.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <com.github.mikephil.charting.charts.BarChart android:id="@+id/chart1" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_above="@+id/seekBar1" /> </RelativeLayout>
  • BarCharts.java
package com.charts.xh.mpandroidcharts; import android.app.Activity; import android.content.Intent; import android.graphics.Color; import android.os.Bundle; import android.util.Log; import android.widget.Toast; import com.charts.xh.mpandroidcharts.com.charts.xh.utils.CustomerValueFormatter; import com.charts.xh.mpandroidcharts.com.charts.xh.utils.MyYValueFormatter; import com.github.mikephil.charting.charts.BarChart; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.Legend.LegendForm; import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.components.XAxis.XAxisPosition; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import java.util.ArrayList; public class BarCharts1 extends Activity implements OnChartValueSelectedListener { private BarChart mChart; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_barchart); mChart = (BarChart) findViewById(R.id.chart1); mChart.setOnChartValueSelectedListener(this); mChart.setDescription("市場拓展表"); mChart.setNoDataTextDescription("You need to provide data for the chart."); mChart.setDrawValueAboveBar(true);//將Y數據顯示在點的上方 // mChart.setDrawBorders(true); // scaling can now only be done on x- and y-axis separately mChart.setPinchZoom(true);//擠壓縮放 mChart.setDrawBarShadow(false); mChart.setDrawGridBackground(false); mChart.setScaleYEnabled(false); mChart.setDoubleTapToZoomEnabled(false);//雙擊縮放 mChart.getXAxis().setPosition(XAxisPosition.BOTTOM);//x軸位置 // create a custom MarkerView (extend MarkerView) and specify the layout // to use for it //自定義 MarkerView MyMarkerView mv = new MyMarkerView(this, R.layout.custom_marker_view); // define an offset to change the original position of the marker // (optional) // mv.setOffsets(-mv.getMeasuredWidth() / 2, -mv.getMeasuredHeight()); // set the marker to the chart mChart.setMarkerView(mv); Legend l = mChart.getLegend();//圖例 l.setPosition(LegendPosition.RIGHT_OF_CHART_INSIDE); l.setTextSize(10f); l.setFormSize(10f); // set the size of the legend forms/shapes l.setForm(LegendForm.CIRCLE); l.setWordWrapEnabled(true); l.setPosition(LegendPosition.BELOW_CHART_CENTER); XAxis xl = mChart.getXAxis(); xl.setLabelRotationAngle(-20);//設置x軸字體顯示角度 //xl.setPosition(XAxisPosition.BOTTOM); YAxis leftAxis = mChart.getAxisLeft(); //leftAxis.setValueFormatter(new LargeValueFormatter());// leftAxis.setValueFormatter(new MyYValueFormatter());//自定義y數據格式化方式 leftAxis.setDrawGridLines(false);//是否畫線 leftAxis.setSpaceTop(30f); leftAxis.setAxisMinValue(0f); // this replaces setStartAtZero(true) mChart.getAxisRight().setEnabled(false); setData(10); } public void setData(int num) { ArrayList<String> xVals = new ArrayList<String>(); for (int i = 0; i < num; i++) { xVals.add( "小謝"+ i); } ArrayList<BarEntry> yVals1 = new ArrayList<BarEntry>(); ArrayList<BarEntry> yVals2 = new ArrayList<BarEntry>(); ArrayList<BarEntry> yVals3 = new ArrayList<BarEntry>(); for (int i = 0; i < num; i++) { float val = (float) (Math.random() * num); yVals1.add(new BarEntry(val, i)); } for (int i = 0; i < num; i++) { float val = (float) (Math.random() * num);; yVals2.add(new BarEntry(val, i)); } for (int i = 0; i < num; i++) { float val = (float) (Math.random() * num); yVals3.add(new BarEntry(val, i)); } // create 3 datasets with different types BarDataSet set1 = new BarDataSet(yVals1, "一季度"); // set1.setColors(ColorTemplate.createColors(getApplicationContext(), // ColorTemplate.FRESH_COLORS)); set1.setColor(Color.rgb(104, 241, 175)); BarDataSet set2 = new BarDataSet(yVals2, "二季度"); set2.setColor(Color.rgb(164, 228, 251)); BarDataSet set3 = new BarDataSet(yVals3, "三季度"); set3.setColor(Color.rgb(242, 247, 158)); ArrayList<IBarDataSet> dataSets = new ArrayList<IBarDataSet>(); dataSets.add(set1); dataSets.add(set2); dataSets.add(set3); BarData data = new BarData(xVals, dataSets); // data.setValueFormatter(new LargeValueFormatter()); // add space between the dataset groups in percent of bar-width data.setValueFormatter(new CustomerValueFormatter()); data.setDrawValues(true); data.setValueTextColor(Color.BLACK); data.setValueTextSize(13); data.setGroupSpace(80f);//設置組數據間距 //data.setValueTypeface(tf); mChart.setData(data); mChart.animateXY(800,800);//圖表數據顯示動畫 mChart.setVisibleXRangeMaximum(15);//設置屏幕顯示條數 mChart.invalidate(); } @Override public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { Log.i("Activity", "Selected: " + e.toString() + ", dataSet: " + dataSetIndex); Toast.makeText(this, e.getXIndex()+"valu"+e.getVal()+e.getData(), } @Override public void onNothingSelected() { Log.i("Activity", "Nothing selected."); } }
  • MyMarkerView .java
package com.charts.xh.mpandroidcharts; import android.content.Context; import android.widget.TextView; import com.github.mikephil.charting.components.MarkerView; import com.github.mikephil.charting.data.CandleEntry; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.Utils; /** * Custom implementation of the MarkerView. * * @author Philipp Jahoda */ public class MyMarkerView extends MarkerView { private TextView tvContent; public MyMarkerView(Context context, int layoutResource) { super(context, layoutResource); tvContent = (TextView) findViewById(R.id.tvContent); } // callbacks everytime the MarkerView is redrawn, can be used to update the // content (user-interface) @Override public void refreshContent(Entry e, Highlight highlight) { if (e instanceof CandleEntry) { CandleEntry ce = (CandleEntry) e; tvContent.setText("" + Utils.formatNumber(ce.getHigh(), 0, true)); } else { tvContent.setText("" + Utils.formatNumber(e.getVal(), 0, true)); } } @Override public int getXOffset(float xpos) { // this will center the marker-view horizontally return -(getWidth() / 2); } @Override public int getYOffset(float ypos) { // this will cause the marker-view to be above the selected value return -getHeight(); } }
  • MyMarkerView 布局文件 custom_marker_view.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="40dp" android:background="@drawable/marker2" > <TextView android:id="@+id/tvContent" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_marginTop="7dp" android:layout_marginLeft="5dp" android:layout_marginRight="5dp" android:text="" android:textSize="12dp" android:textColor="@android:color/white" android:ellipsize="end" android:singleLine="true" android:textAppearance="?android:attr/textAppearanceSmall" /> </RelativeLayout>
  • Y軸線數據格式化 MyYValueFormatter .java
package com.charts.xh.mpandroidcharts.com.charts.xh.utils; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.formatter.YAxisValueFormatter; import java.text.DecimalFormat; public class MyYValueFormatter implements YAxisValueFormatter { private DecimalFormat mFormat; public MyYValueFormatter() { mFormat = new DecimalFormat("###,###,###,##0"); } @Override public String getFormattedValue(float value, YAxis yAxis) { return mFormat.format(value); } }
  • Gradle 依賴
repositories {
    maven { url "https://jitpack.io" } } dependencies { compile 'com.github.PhilJay:MPAndroidChart:v2.2.5' }

如果用的Eclipse只需要將jar包拷貝到項目libs目錄下,即可開發是用MPAndroidCharts庫,點擊下載jar包

MPAndroidCharts常見問題

1 . 如何顯示隱藏Y軸線及自定義軸線的顯示樣式

mChart.getAxisLeft().setEnabled(false) //隱藏Y軸左邊軸線,此時標簽數字也隱藏
mChart.getAxisRight().setEnabled(false) //隱藏Y軸右邊軸線,此時標簽數字也隱藏
如果想隱藏軸線但是想顯示數字標簽:
mChart.getAxisRight().setDrawAxisLine(false);

2 . Y軸線數據標簽怎么自己控制顯示個數

mChart.getAxisLeft().setLabelCount(8, false);//此時設置了分8個,可根據自己喜好設置

3 . 怎么設置軸線顏色,寬度等信息

YAxis leftAxis = mChart.getAxisLeft();
leftAxis . setPosition(YAxisLabelPosition.OUTSIDE_CHART);/ /顯示軸線內部INSIDE_CHART
leftAxis.setAxisLineColor(Color.parseColor("#ff0000"));//設置軸線顏色:leftAxis.setAxisLineWidth(1);// 設置軸線寬度
leftAxis.setTextSize(20);//設置y軸標簽字體大小
leftAxis.setTypeface();//設置自定義字體
leftAxis.setDrawGridLines(Boolean );//設置是否顯示網格線,

4 . 怎么將Y軸線數據前面加上¥人民幣符號

import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.formatter.YAxisValueFormatter; import java.text.DecimalFormat; public class MyYValueFormatter implements YAxisValueFormatter { private DecimalFormat mFormat; public MyYValueFormatter() { mFormat = new DecimalFormat("###,###,###,##0"); } @Override public String getFormattedValue(float value, YAxis yAxis) { return "¥"+mFormat.format(value); } }

5 . 圖表里面邊緣標簽數據顯示不全,顯示到界面外面如何處理


此圖右邊數據顯示不全
mChart.setExtraLeftOffset(float); mChart.setExtraTopOffset(float); mChart.setExtraRightOffset(float); mChart.setExtraBottomOffset(float); mChart.setExtraOffsets(float left, float top, float right, float bottom);//此種方法可以一次設置上下左右偏移量。根據自己數據哪個地方顯示不全,對應調用方法。

6 . 怎么實現X軸 對應的Y數據顯示整型


這里寫圖片描述
import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.utils.ViewPortHandler; import java.text.DecimalFormat; public class CustomerValueFormatter implements ValueFormatter { private DecimalFormat mFormat; public CustomerValueFormatter() { //此處是顯示數據的方式,顯示整型或者小數后面小數位數自己隨意確定 mFormat = new DecimalFormat("###,###,###,##0"); } @Override public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { return mFormat.format(value);//數據前或者后可根據自己想要顯示的方式添加 } }

注:百分比源碼自帶PercentFormatter,當然上面自定義可以定義你任何想要的方式。

7 . 將x軸標簽傾斜顯示(如問題6里面x軸標簽效果)

XAxis xl = mChart.getXAxis();
xl.setLabelRotationAngle(-20);//設置x軸字體顯示角度 xl.setPosition(XAxisPosition.BOTTOM);//設置X軸的位置TOP, BOTTOM, BOTH_SIDED, TOP_INSIDE, BOTTOM_INSIDE xl.setSpaceBetweenLabels(int spaceCharacters)//設置Lable之間的距離(字符),小於距離將不顯示,需要放大圖標才能看到

8 . 設置x軸對應y數據

data.setDrawValues(false);//隱藏數據 data.setValueTextSize(20f);//設置字體大小 data.setValueTypeface(mTf);//自定義字體 setValueTextColor(int color)//設置字體顏色 setValueTextColors(List<Integer> colors)//可設置多種顏色

9 . Barchart表設置柱體之間的距離無效


這里寫圖片描述


BarChart柱體間距有兩種方式,如上圖的1和2:

  • 設置1間距
BarDataSet set1 = new BarDataSet(yVals1, "DataSet"); set1.setBarSpacePercent(50f);
  • 設置2間距
data.setGroupSpace(float);//設置一頁顯示的數據條數,超出的數量需要滑動查看:

所以設置間距要看你的數據,及設置的是哪個間距,只有調用對應的方法間距才能生效。由於這個間隔設置是按百分比的,如果數據較多用戶體驗會很差,可以適當配合問題10設置一頁顯示的數量,可美觀界面。

10 . 一個頁面顯示的數據太多了,都不看清楚,怎么樣設置一個頁面顯示固定條數的數據,如果數據太多需要手動滑動看到

//設置一頁顯示的數據條數,超出的數量需要滑動查看: mChart.setVisibleXRangeMaximum(int);//需要在設置數據源后生效 barChart.setVisibleXRangeMinimum();//設置最少數量,不常用。 注:上面方法老的版本是沒用此方法的可以用: setVisibleXRange(float minXRange, float maxXRange)

11 . 如何設置圖例樣式

Legend l = mChart.getLegend();
//l.setEnable(false);//不顯示圖例,默認true 顯示 /**圖例位置的枚舉類有下面幾種: RIGHT_OF_CHART, RIGHT_OF_CHART_CENTER, RIGHT_OF_CHART_INSIDE, LEFT_OF_CHART, LEFT_OF_CHART_CENTER, LEFT_OF_CHART_INSIDE, BELOW_CHART_LEFT, BELOW_CHART_RIGHT, BELOW_CHART_CENTER, ABOVE_CHART_LEFT, ABOVE_CHART_RIGHT, ABOVE_CHART_CENTER, PIECHART_CENTER */ l.setPosition(LegendPosition.RIGHT_OF_CHART_INSIDE);//設置圖例的位置 l.setTextSize(10f); l.setFormSize(10f); // set the size of the legend forms/shapes l.setForm(LegendForm.CIRCLE);//設置圖例形狀, SQUARE(方格) CIRCLE(圓形) LINE(線性) l.setWordWrapEnabled(true);//此方法影響性能,盡量不用,默認是fasle的

12 . 怎么將圖表上的節點數據顯示成對應的x軸數據和y軸數據拼接顯示,如下效果


這里寫圖片描述
package com.charts.xh.mpandroidcharts.com.charts.xh.utils; import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.utils.ViewPortHandler; import java.text.DecimalFormat; import java.util.List; /** * Created by xiehui on 2016/7/31. */ public class CustomerPercentFormatter implements ValueFormatter { protected DecimalFormat mFormat; protected List<String> mXVals; public CustomerPercentFormatter(ChartData data) { mFormat = new DecimalFormat("###,###,##0.0"); mXVals = data.getXVals(); } /** * Allow a custom decimalformat * * @param format */ public CustomerPercentFormatter(DecimalFormat format) { this.mFormat = format; } // ValueFormatter @Override public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { return mXVals.get(entry.getXIndex()) + " : " + mFormat.format(value) + " %"; } }

后語

第一次寫博客,由於水平有限可能有一些理解不是很深刻,可能有很多不足的地方,希望大家指正,本文是出於自己學習的目的,做一些記錄,當然如果對大家有幫助在下實在榮幸。
注:寫博客好難啊...真佩服那些經常寫博客的大神。



文/Code4Android(簡書作者)
原文鏈接:http://www.jianshu.com/p/9fc2b3942163
著作權歸作者所有,轉載請聯系作者獲得授權,並標注“簡書作者”。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM