MPAndroidChart使用记录
文章目錄
- 前言
- 舉例說(shuō)明一些概念
- Chart設(shè)置
- 補(bǔ)充1:ViewPortHandler類(lèi)
- 補(bǔ)充2:設(shè)置空數(shù)據(jù)文案
- 補(bǔ)充3:設(shè)置觸摸監(jiān)聽(tīng)并打印當(dāng)前坐標(biāo)
- 補(bǔ)充4:給chart設(shè)置一組數(shù)據(jù)
- 折線圖示例
- 柱狀圖示例
- 餅狀圖示例
- 補(bǔ)充5:關(guān)于設(shè)置高亮數(shù)據(jù)
- 補(bǔ)充6:設(shè)置x軸標(biāo)簽換行
- ChartData
- 刷新列表的2種方式
- ComponentBase
- Description
- LimitLine
- Legend
- 設(shè)置自定義圖例
- 設(shè)置圖例自動(dòng)換行
- AxisBase
- MarkerView
- 補(bǔ)充:使用SpannableStringBuilder顯示不一樣的字體
- 問(wèn)題記錄
- 問(wèn)題1:無(wú)法在MPAndroidChart中設(shè)置Double值
- 問(wèn)題2:ValueFormatter處出錯(cuò)ArrayIndexOutOfBoundsException
- AAChart
- 后話(huà)
前言
說(shuō)到圖表,我第一時(shí)間就想到了大名鼎鼎的MPAndroidChart,這個(gè)庫(kù)在在IOS端叫Charts。如果是網(wǎng)頁(yè)端,ECharts庫(kù)很好用。
本文中使用庫(kù)版本為MPAdnroidChart庫(kù)3.1.0。
舉例說(shuō)明一些概念
- Chart是一個(gè)ViewGroup,這和我們了解的大部分自定義View相同。
- 上圖為BarChart,簡(jiǎn)單說(shuō)明下:x軸、左邊的y軸、右邊的y軸(上圖沒(méi)顯示)、x軸的標(biāo)簽(上圖 1980、1982…)、左邊y軸標(biāo)簽(上圖 0、40、80…)、圖例(說(shuō)明有幾個(gè)數(shù)據(jù)集)、LimitLine(上圖為y軸上的加粗虛線,文案為Good Level)、網(wǎng)格線(上圖只在x軸上繪制了網(wǎng)格線,而且網(wǎng)格線默認(rèn)是實(shí)線,與坐標(biāo)垂直)、數(shù)據(jù)(上圖條型柱)
- MarkerView:可以簡(jiǎn)單理解為,自定義的彈出界面,見(jiàn)下圖
- ValueFormatter使用,可以處理x、y軸標(biāo)簽文案顯示,還可以處理markerview彈出框中文案顯示。
- Entry這個(gè)東西是必帶 x、y坐標(biāo)的,還可以附帶一個(gè)Object對(duì)象,作用當(dāng)然是使用ValueFormatter時(shí),根據(jù)對(duì)象和坐標(biāo)值顯示文案。
Chart設(shè)置
提示:下面的設(shè)置有許多是可以注釋掉的,因?yàn)槭悄J(rèn)值
//設(shè)置viewgroup背景色 chart.setBackgroundColor(Color.WHITE); //設(shè)置繪制網(wǎng)格背景 chart.setDrawGridBackground(true); //設(shè)置網(wǎng)格背景色 chart.setGridBackgroundColor(Color.BLUE); //設(shè)置不繪制邊框 //chart.setDrawBorders(false);//設(shè)置圖表上啟用了觸摸手勢(shì) //chart.setTouchEnabled(true); //設(shè)置可以縮放圖表 //chart.setScaleEnabled(true); //設(shè)置可以用手指移動(dòng)圖表 //chart.setDragEnabled(true); //設(shè)置啟用捏縮放標(biāo)志 chart.setPinchZoom(true);//不顯示圖表描述文字 chart.getDescription().setEnabled(false); //不顯示x軸 chart.getXAxis().setEnabled(false); //不顯示右邊y軸 chart.getAxisRight().setEnabled(false); //不顯示左邊y軸 chart.getAxisLeft().setEnabled(false); //不顯示圖例 chart.getLegend().setEnabled(false);//設(shè)置makerview,即選中值時(shí)出現(xiàn)的標(biāo)志顯示框,一般是自定義 //...省略了MarkerView創(chuàng)建過(guò)程 chart.setMarker(mv);//返回代表所有x標(biāo)簽的對(duì)象 XAxis xAxis = chart.getXAxis(); //返回左側(cè)的y軸對(duì)象 YAxis yAxisLeft=chart.getAxisLeft(); //返回右側(cè)y軸對(duì)象 YAxis yAxisRight=chart.getAxisRight();//執(zhí)行默認(rèn)動(dòng)畫(huà)在X軸上對(duì)圖表進(jìn)行渲染,時(shí)長(zhǎng)1.5s chart.animateX(1500); //執(zhí)行默認(rèn)動(dòng)畫(huà)在Y軸上對(duì)圖表進(jìn)行渲染,時(shí)長(zhǎng)1.5s chart.animateY(1500); //執(zhí)行默認(rèn)動(dòng)畫(huà)分別在X軸和Y軸上對(duì)圖表進(jìn)行渲染 chart.animateXY(1500,1500); //默認(rèn)動(dòng)畫(huà)是線形的,具體查看com.github.mikephil.charting.animation.Easing類(lèi) //執(zhí)行指定動(dòng)畫(huà)在Y軸上對(duì)圖表進(jìn)行渲染,時(shí)長(zhǎng)2s chart.animateY(2000, Easing.EaseInCubic);//獲取圖表的圖例對(duì)象 chart.getLegend();//獲取所有數(shù)據(jù) //獲取的是一個(gè)ChartData類(lèi)型的對(duì)象,ChartData內(nèi)有一個(gè)列表,它可以存儲(chǔ)任意實(shí)現(xiàn)了IDataSet接口的對(duì)象,比如說(shuō)BarDataSet、LineDataSet、PinDataSet這些。關(guān)于數(shù)據(jù)和數(shù)據(jù)集我們后面再說(shuō)。 chart.getData()//設(shè)置所有數(shù)據(jù) data必須是ChartData類(lèi)型,像LinData、BarData、PieData這些都是ChartData的子類(lèi)。 chart.setData(data);補(bǔ)充1:ViewPortHandler類(lèi)
chart類(lèi)內(nèi)部有一個(gè)ViewPortHandler對(duì)象,他存儲(chǔ)著可繪制圖形區(qū)域、允許最大拖曳距離、允許最大比率、當(dāng)前平移位置等。
示例-讓當(dāng)前chart x軸放大四倍、y軸不變
//新建一個(gè)矩陣 Matrix matrix = new Matrix(); // x軸放大4倍,y不變 matrix.postScale(4.0f, 1.0f); chart.getViewPortHandler().refresh(matrix, mChart, true);補(bǔ)充2:設(shè)置空數(shù)據(jù)文案
/*** 顯示無(wú)數(shù)據(jù)的提示** @param mChart*/ public static void showNoDataText(Chart chart) {chart.clear();chart.notifyDataSetChanged();chart.setNoDataText("沒(méi)有數(shù)據(jù)");chart.setNoDataTextColor(Color.WHITE);// 記得最后要刷新一下chart.invalidate(); }補(bǔ)充3:設(shè)置觸摸監(jiān)聽(tīng)并打印當(dāng)前坐標(biāo)
//先確保圖表允許觸摸事件 chart.setTouchEnabled(true); //設(shè)置監(jiān)聽(tīng) chart.setOnChartValueSelectedListener(new OnChartValueSelectedListener() {@Overridepublic void onValueSelected(Entry e, Highlight h) {//打印坐標(biāo)Log.i("Entry selected", e.toString());}@Overridepublic void onNothingSelected() {Log.i("Nothing selected", "Nothing selected.");} });補(bǔ)充4:給chart設(shè)置一組數(shù)據(jù)
折線圖示例
//造一點(diǎn)數(shù)據(jù),每一個(gè)數(shù)據(jù)點(diǎn)都綁定一個(gè)水費(fèi)信息WaterInfo ArrayList<Entry> values = new ArrayList<>(); for (int i = 0; i < 45; i++) {float val = (float) (Math.random() * 200);values.add(new Entry(i, val, new WaterInfo(i,i*0.5f))); } LineDataSet lineDataSetWater; //創(chuàng)建一個(gè)line數(shù)據(jù)集并設(shè)置label字段 lineDataSetWater = new LineDataSet(values, "lineDataSetWater"); //設(shè)置不繪制每個(gè)數(shù)據(jù)節(jié)點(diǎn)的小圖標(biāo) 常用于數(shù)據(jù)源是BarEntry(float float y, Drawable icon)這種類(lèi)型的 lineDataSetWater.setDrawIcons(false); //設(shè)置模式為貝塞爾曲線線 lineDataSetWater.setMode(LineDataSet.Mode.HORIZONTAL_BEZIER); //設(shè)置數(shù)據(jù)線為虛線 默認(rèn)是實(shí)線 lineDataSetWater.enableDashedLine(10f, 5f, 0f); //設(shè)置不顯示數(shù)據(jù)值 lineDataSetWater.setDrawValues(false); //設(shè)置顯示數(shù)據(jù)值字體大小 lineDataSetWater.setValueTextSize(10f); //設(shè)置曲線顏色 lineDataSetWater.setColor(Color.BLACK); //設(shè)置畫(huà)圓點(diǎn) lineDataSetWater.setDrawCircles(true); //設(shè)置不畫(huà)圓心,即畫(huà)實(shí)心圓點(diǎn) lineDataSetWater.setDrawCircleHole(false); //設(shè)置圓點(diǎn)的半徑 lineDataSetWater.setCircleRadius(3f); //設(shè)置圓點(diǎn)顏色 lineDataSetWater.setCircleColor(Color.RED); //設(shè)置線寬 lineDataSetWater.setLineWidth(1f); //不顯示選中指示線 默認(rèn)顯示 //lineDataSetWater.disableDashedLine(); //設(shè)置選中指示線為虛線 lineDataSetWater.enableDashedHighlightLine(10f, 5f, 0f); //設(shè)置允許填充線到坐標(biāo)軸的區(qū)域 lineDataSetWater.setDrawFilled(true); lineDataSetWater.setFillFormatter(new IFillFormatter() {@Overridepublic float getFillLinePosition(ILineDataSet dataSetLineDataProvider dataProvider) {return chart.getAxisLeft().getAxisMinimum();} }); //設(shè)置填充區(qū)域 if (android.os.Build.VERSION.SDK_INT >= 18) {//設(shè)置填充區(qū)域?yàn)橐粋€(gè)漸變紅的DrawableDrawable drawable=ContextCompat.getDrawable(getBaseContext(),R.drawable.fade_red);lineDataSetWater.setFillDrawable(drawable); } else {//設(shè)置漸變區(qū)域填充色lineDataSetWater.setFillColor(Color.BLUE); } ArrayList<ILineDataSet> dataSets = new ArrayList<>(); dataSets.add(lineDataSetWater); //新建一個(gè)LineData,并加入數(shù)據(jù)集 LineData data = new LineData(dataSets); //給圖表設(shè)置數(shù)據(jù)源 chart.setData(data);tips:如果是混合圖,使用CombinedChart和CombinedData.
柱狀圖示例
BarChart chart =findViewById(R.id.chart); chart = findViewById(R.id.chart1); //設(shè)置圖表背景色 chart.setBackgroundColor(Color.WHITE); //設(shè)置不繪制陰影 chart.setDrawBarShadow(false); //設(shè)置繪制數(shù)值 chart.setDrawValueAboveBar(true); //設(shè)置不顯示描述框 chart.getDescription().setEnabled(false); //執(zhí)行默認(rèn)動(dòng)畫(huà)分別在X軸和Y軸上對(duì)圖表進(jìn)行渲染 chart.animateXY(1500,1500); //設(shè)置監(jiān)聽(tīng)器 chart.setOnChartValueSelectedListener(new OnChartValueSelectedListener() {private final RectF onValueSelectedRectF = new RectF();@Overridepublic void onValueSelected(Entry e, Highlight h) {if (e == null) return;RectF bounds = onValueSelectedRectF;chart.getBarBounds((BarEntry) e, bounds);MPPointF position = chart.getPosition(e, AxisDependency.LEFT);//打印矩形信息Log.i("bounds", bounds.toString());Log.i("x-index", "low: " + chart.getLowestVisibleX() + ", high: "+ chart.getHighestVisibleX());MPPointF.recycleInstance(position);}@Overridepublic void onNothingSelected() { } }); //設(shè)置一屏最大顯示數(shù)據(jù)量為19(注意是20-1,這個(gè)和顯示ValuesText有點(diǎn)聯(lián)系,盡量設(shè)置大,設(shè)置小了,ValuesText會(huì)不顯示) //只有當(dāng)DataSet允許畫(huà)值的時(shí)候,才有作用 chart.setMaxVisibleValueCount(20); //設(shè)置不允許雙指縮放 chart.setPinchZoom(false);//...省略設(shè)置軸線、圖例、markerview等相關(guān) ArrayList<BarEntry> values = new ArrayList<>(); for (int i = 1; i < 10; i++) {float val = (float) (Math.random() * (range + 1));if (i % 2 == 0) {//帶drawable的數(shù)據(jù)源values.add(new BarEntry(i, val, getResources().getDrawable(R.drawable.star)));} else {values.add(new BarEntry(i, val));} } //label字段和圖例相關(guān) BarDataSet barDataSet = new BarDataSet(values, "2017"); //設(shè)置不畫(huà)小圖標(biāo) barDataSet.setDrawIcons(false); int startColor1 = ContextCompat.getColor(this, android.R.color.holo_orange_light); int startColor2 = ContextCompat.getColor(this, android.R.color.holo_blue_light); int startColor3 = ContextCompat.getColor(this, android.R.color.holo_orange_light); int endColor1 = ContextCompat.getColor(this, android.R.color.holo_blue_dark); int endColor2 = ContextCompat.getColor(this, android.R.color.holo_purple); int endColor3 = ContextCompat.getColor(this, android.R.color.holo_green_dark);List<GradientColor> gradientColors = new ArrayList<>(); gradientColors.add(new GradientColor(startColor1, endColor1)); gradientColors.add(new GradientColor(startColor2, endColor2)); gradientColors.add(new GradientColor(startColor3, endColor3)); //設(shè)置漸變色集合 集合大小隨意 barDataSet.setGradientColors(gradientColors);List<Integer> colors=new ArrayList<>(); colors.add(startColor1); colors.add(startColor2); colors.add(startColor3); //設(shè)置字體顏色合集,集合大小隨意 barDataSet.setValueTextColors(colors);ArrayList<IBarDataSet> dataSets = new ArrayList<>(); dataSets.add(barDataSet);//創(chuàng)建一個(gè)bardata BarData data = new BarData(dataSets); //可以某個(gè)dataset單獨(dú)設(shè)置,這里是設(shè)置所有ValueText data.setDrawValues(true); data.setValueTextSize(10f); data.setValueTypeface(tfLight); //設(shè)置bar的寬度百分率(默認(rèn)0.85),大于1會(huì)出現(xiàn)柱子重疊 data.setBarWidth(0.5f);chart.setData(data);貼個(gè)圖
餅狀圖示例
PieChart chart=findViewById(R.id.chart); //設(shè)置在餅圖切片中顯示百分比值 chart.setUsePercentValues(true); //設(shè)置在餅圖切片中顯示條目信息 chart.setDrawEntryLabels(true); //條目信息相關(guān)設(shè)置 顏色、樣式、字體大小等 chart.setEntryLabelColor(Color.WHITE); chart.setEntryLabelTypeface(tfRegular); chart.setEntryLabelTextSize(12f); //設(shè)置不顯示描述框 chart.getDescription().setEnabled(false); //設(shè)置圖表視圖左、上、右、下 額外偏移量 //此偏移量,不會(huì)影響設(shè)置了在chart外部的圖例等 chart.setExtraOffsets(5, 10, 5, 5); //設(shè)置觸摸后圖表繼續(xù)滾動(dòng),默認(rèn)為true(類(lèi)比手動(dòng)轉(zhuǎn)大轉(zhuǎn)盤(pán),慢慢停下) chart.setDragDecelerationEnabled(true); //設(shè)置減速摩擦系數(shù) 默認(rèn)0.9 chart.setDragDecelerationFrictionCoef(-1f);//設(shè)置繪制中間文本 chart.setDrawCenterText(true); //設(shè)置中間文字字體樣式 chart.setCenterTextTypeface(tfLight); //設(shè)置中間字體 generateCenterSpannableText chart.setCenterText(generateCenterSpannableText());//設(shè)置允許繪制圖表中間的洞 chart.setDrawHoleEnabled(true); //設(shè)置洞顏色 chart.setHoleColor(Color.WHITE); //設(shè)置透明圓顏色 chart.setTransparentCircleColor(Color.WHITE); //設(shè)置透明圓透明度 chart.setTransparentCircleAlpha(110); //設(shè)置洞半徑 chart.setHoleRadius(58f); //設(shè)置透明圓半徑 chart.setTransparentCircleRadius(61f);//允許手勢(shì)觸摸旋轉(zhuǎn) chart.setRotationEnabled(true); //設(shè)置旋轉(zhuǎn)偏移量,默認(rèn)270f,單位:度 chart.setRotationAngle(0); //設(shè)置允許點(diǎn)擊手勢(shì)后模塊高亮 chart.setHighlightPerTapEnabled(true);//設(shè)置選中值監(jiān)聽(tīng)器 chart.setOnChartValueSelectedListener(new OnChartValueSelectedListener() {@Overridepublic void onValueSelected(Entry e, Highlight h) {if (e == null)return;Log.i("VAL SELECTED","Value: " + e.getY() + ", index: " + h.getX()+ ", DataSet index: " + h.getDataSetIndex());}@Overridepublic void onNothingSelected() {} });/*chart.setDrawHoleEnabled(true); chart.setDrawSlicesUnderHole(false); //設(shè)置以彎曲方式繪制切片,僅在啟用繪制孔Hole,并且未在孔下方繪制切片的情況生效 chart.setDrawRoundedSlices(true);*/設(shè)置數(shù)據(jù)
ArrayList<PieEntry> entries = new ArrayList<>(); for (int i = 0; i < 5 ; i++) {entries.add(new PieEntry((float) ((Math.random() * 100) + 100 / 5),"Data"+i));}PieDataSet dataSet = new PieDataSet(entries, "Election Results"); //設(shè)置不畫(huà)小圖標(biāo) dataSet.setDrawIcons(false); //設(shè)置切片Slice之間空間(unit:dp) dataSet.setSliceSpace(3f); //設(shè)置小圖表偏移集合 // dataSet.setIconsOffset(new MPPointF(40, 40)); //設(shè)置數(shù)據(jù)集中突出顯示的切片與圖表中心距離 (unit:dp) 點(diǎn)擊手勢(shì) //注意:在彎曲方式繪制切片時(shí),此設(shè)置無(wú)效 dataSet.setSelectionShift(5f);//創(chuàng)建一個(gè)顏色集合 ArrayList<Integer> colors = new ArrayList<>(); //chart庫(kù)自帶了很多顏色集合,查看工具類(lèi)utils下ColorTemplate for (int c : ColorTemplate.COLORFUL_COLORS) colors.add(c); // colors.add(ColorTemplate.getHoloBlue()); //設(shè)置顏色集合dataSet.setColors(colors);//創(chuàng)建一個(gè)PieData PieData data = new PieData(dataSet); //庫(kù)自帶的PercentFormatter data.setValueFormatter(new PercentFormatter(chart)); //設(shè)置數(shù)據(jù)文本字體大小 data.setValueTextSize(12f); //設(shè)置數(shù)據(jù)文本顏色 data.setValueTextColor(Color.WHITE); //設(shè)置數(shù)據(jù)文本樣式 data.setValueTypeface(tfLight); chart.setData(data);補(bǔ)充5:關(guān)于設(shè)置高亮數(shù)據(jù)
什么是高亮值,選中值監(jiān)聽(tīng)器的onValueSelected方法里不是返回了一個(gè)Highlight對(duì)象,他包含了要突出顯示的值的一些信息。比如這個(gè)值的x值和y值、當(dāng)前值在x方向像素和y方向像素、這個(gè)值的數(shù)據(jù)集在數(shù)據(jù)中的索引等。如上圖突出的數(shù)據(jù)“74”,被2條坐標(biāo)標(biāo)記出來(lái)了。
//需要高亮的數(shù)據(jù)集設(shè)置為null chart.highlightValues(null); chart.invalidate();設(shè)置dataSet或者Data的屬性也可:
//LineDataSet為例 linDataSet.setHighlightEnabled(false);//LineData為例 linData.setHighlightEnabled(false);補(bǔ)充6:設(shè)置x軸標(biāo)簽換行
x軸顯示時(shí)間,格式為yyyy-MM-dd HHmmSS,要求換行顯示2部分,條件為空格。
/*** 自定義AxisRenderer */ public class CustomXAxisRenderer extends XAxisRenderer {public CustomXAxisRenderer(ViewPortHandler viewPortHandler, XAxis xAxis, Transformer trans) {super(viewPortHandler, xAxis, trans);}@Overrideprotected void drawLabel(Canvas c, String formattedLabel, float x, float y, MPPointF anchor, float angleDegrees) {String[] lines = formattedLabel.split(" ");int length = lines.length;for (int i = 0; i < length; i++) {float offset = i * mAxisLabelPaint.getTextSize();Utils.drawXAxisValue(c, lines[i], x, y + offset, mAxisLabelPaint, anchor, angleDegrees);}} }設(shè)置
chart.setXAxisRenderer(new CustomXAxisRenderer(chart.getViewPortHandler(), xAxis,chart.getTransformer(YAxis.AxisDependency.LEFT)));ChartData
說(shuō)到ChartData就必須說(shuō)IDataSet接口和Entry對(duì)象。
其內(nèi)部有一個(gè)數(shù)據(jù)集列表,并且維護(hù)著x軸和y軸最大最小值:mYMax、mYMin、mXMax、mXMin,通過(guò)遍歷Entry獲取。
刷新列表的2種方式
刷新整個(gè)表
可以直接調(diào)用Chart的setData方法。
部分刷新
通過(guò)操作Entry列表,并依次調(diào)用Chart的notifyDataSetChanged和invalidate方法。
至于怎么操作Entry列表,圖表中數(shù)據(jù)集可以調(diào)用下面方法
//IDataSet接口中有關(guān)方法 <T extends Entry>//添加一條數(shù)據(jù) boolean addEntry(T e); //移除某條數(shù)據(jù) boolean removeEntry(T e); //移除第一條數(shù)據(jù) boolean removeFirst(); //移除最后一條數(shù)據(jù) boolean removeLast();或者直接調(diào)用ChartData中方法
//ChartData中有關(guān)方法 <T extends IDataSet<? extends Entry>>//給此數(shù)據(jù)中某個(gè)數(shù)據(jù)集添加一條數(shù)據(jù) addEntry(Entry e, int dataSetIndex) //從此數(shù)據(jù)中某個(gè)數(shù)據(jù)集中移除某條數(shù)據(jù) boolean removeEntry(Entry e, int dataSetIndex) //給此數(shù)據(jù)添加一個(gè)數(shù)據(jù)集 addDataSet(T d) //從此數(shù)據(jù)中移除某個(gè)數(shù)據(jù)集 boolean removeDataSet(T d)最后別忘記刷新列表
chart.notifyDataSetChanged(); // let the chart know it's data changed chart.invalidate(); // refreshComponentBase
看了以下發(fā)現(xiàn),AxisBase、Description、Legend、LimitLine都繼承他。
設(shè)置了一些默認(rèn)值,比如是否繪制、偏移量、字體大小、字體樣式。
protected boolean mEnabled = true; protected float mXOffset = 5f; protected float mYOffset = 5f; protected Typeface mTypeface = null; protected float mTextSize = Utils.convertDpToPixel(10f); protected int mTextColor = Color.BLACK;-
Description
圖表描述字段
Description description=chart.getDescription(); //設(shè)置顯示位置(unit:px) 默認(rèn)位置為chart的寬高減去一些偏移量,也就是說(shuō)不設(shè)置這個(gè),默認(rèn)在右下角 description.setPosition(100,100); //設(shè)置字體大小 最大24,最小6 description.setTextSize(24f); //設(shè)置文本 description.setText("Passion"); //設(shè)置字體對(duì)齊方式為相對(duì)Position左對(duì)齊,默認(rèn)右對(duì)齊 description.setTextAlign(Paint.Align.LEFT);-
LimitLine
限制線,不是所有的chart都支持添加LimitLine。常見(jiàn)支持的有LinChart、BarChart、ScatterChart等。
注意事項(xiàng):
- 一條坐標(biāo)線最多只能添加6個(gè)限制線。
- 限制線并沒(méi)有限制作用,真正的限制在于你對(duì)數(shù)據(jù)的處理。
- 添加到某個(gè)坐標(biāo)線上的限制線,和他是垂直的。
示例#創(chuàng)建一個(gè)告警線,設(shè)置不遮蓋數(shù)據(jù),添加到左邊的y軸。
//創(chuàng)建一個(gè)告警線(位置在坐標(biāo)軸150f值上,標(biāo)簽名llYAxis) LimitLine llYAxis = new LimitLine(150f, "llYAxis"); //設(shè)置線寬(unit dp) 最小0.2,最大12 llYAxis.setLineWidth(4f); //設(shè)置允許虛線,lineLength、spaceLength、phase llYAxis.enableDashedLine(10f, 10f, 0f); //設(shè)置標(biāo)簽名顯示位置 //llYAxis.setLabelPosition(LimitLabelPosition.RIGHT_TOP); //設(shè)置字體大小(unit:dp) //llYAxis.setTextSize(10f); //設(shè)置字體樣式 Typeface tf=Typeface.createFromAsset(getAssets(), "lqh_kai.ttf"); llYAxis.setTypeface(tf);//設(shè)置不遮擋數(shù)據(jù) YAxis yAxisLeft = chart.getAxisLeft(); yAxisLeft.setDrawLimitLinesBehindData(true);//添加告警線 yAxisLeft.addLimitLine(llYAxis);-
Legend
注意事項(xiàng):只有給chart設(shè)置數(shù)據(jù),圖例的設(shè)置才有用。
圖例設(shè)置示例
Legend l = chart.getLegend(); //設(shè)置格式為線性 l.setForm(LegendForm.LINE); //設(shè)置字體樣式(tf為字體樣式,一般來(lái)從于assets文件ttf文件。) //Typeface tf=Typeface.createFromAsset(getAssets(), "lqh_kai.ttf"); l.setTypeface(tf); //設(shè)置字體大小 單位是dp l.setTextSize(11f); //設(shè)置字體顏色 l.setTextColor(Color.BLACK);//設(shè)置位置在底部 l.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM); //設(shè)置位置在最左邊 l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.LEFT); //設(shè)置圖例方向?yàn)樗?l.setOrientation(Legend.LegendOrientation.HORIZONTAL); //設(shè)置圖例是在圖表內(nèi)部繪制 l.setDrawInside(true); //圖例默認(rèn)x、y方向偏移量為5dp //設(shè)置圖例Y軸偏移量 (unit:dp) l.setYOffset(8f); //設(shè)置圖例X軸偏移量 (unit:dp) l.setXOffset(16f);設(shè)置自定義圖例
在BarChart里,自動(dòng)生成的圖例的數(shù)量和BarDataSet的數(shù)量有關(guān)。但是一般的場(chǎng)景是只有一組數(shù)據(jù),那怎么樣顯示圖例呢,總不能創(chuàng)建N個(gè)BarDataSet,每個(gè)數(shù)據(jù)集只放一個(gè)數(shù)據(jù)點(diǎn)吧。那還不如自定義,使用LegendEntry 。
來(lái)段偽代碼
然后通過(guò)setCustom(List entries)方法設(shè)置即可。
設(shè)置圖例自動(dòng)換行
Legend類(lèi)里面有一個(gè)參數(shù)mWordWrapEnabled,默認(rèn)是false,意思是是否要自動(dòng)換行。
使用下面setWordWrapEnabled方法即可打開(kāi)自動(dòng)換行,但是要注意不支持所有類(lèi)型圖例。我愣是沒(méi)看懂:this is currently supported only for:BelowChartLeft, BelowChartRight, BelowChartCenter。可以實(shí)踐一下,如果不能滿(mǎn)足要求,還是拉源碼去改吧。
示例
Legend l = chart.getLegend(); l.setWordWrapEnabled(true); //圖例占據(jù)整個(gè)chart view的最大百分比,通常用來(lái)控制換行(default: 0.95f (95%)) l.setMaxSizePercent(0.95f);-
AxisBase
坐標(biāo)線,比較常見(jiàn)的XAxis和YAxis都繼承自他。
示例-設(shè)置X軸
//設(shè)置不顯示x軸線 默認(rèn)顯示 xAxis.setDrawAxisLine(false); //設(shè)置x軸線的顏色 默認(rèn)灰色 xAxis.setAxisLineColor(Color.DKGRAY); //設(shè)置不從x軸繪制網(wǎng)格線 默認(rèn)繪制 xAxis.setDrawGridLines(false); xAxis.enableGridDashedLine(10f, 10f, 0f); //設(shè)置x方向網(wǎng)格線的顏色 默認(rèn)灰色 xAxis.setGridColor(Color.LTGRAY); //設(shè)置x軸數(shù)據(jù)標(biāo)簽相對(duì)圖表的位置 默認(rèn)TOP xAxis.setPosition(XAxis.XAxisPosition.BOTTOM); //設(shè)置x軸最大值,不設(shè)置也會(huì)根據(jù)數(shù)據(jù)集計(jì)算出 //常用于數(shù)據(jù)量較多時(shí),限制一屏幕顯示的量 xAxis.setAxisMaximum(1000f); //設(shè)置x軸最小值,不設(shè)置也會(huì)根據(jù)數(shù)據(jù)集計(jì)算出 xAxis.setAxisMinimum(200f); //設(shè)置x軸文字的大小 xAxis.setTextSize(12f); //設(shè)置x軸數(shù)據(jù)偏移量 xAxis.setYOffset(10f); //設(shè)置x軸標(biāo)簽數(shù)組格式處理器 ValueFormatter和IndexAxisValueFormatter都行,重寫(xiě)getFormattedValue返回你想要的 // 如不不設(shè)置,默認(rèn)使用DefaultAxisValueFormatter,DecimalFormat格式化數(shù)據(jù),格式"###,###,###,##0" xAxis.setValueFormatter(new IndexAxisValueFormatter(){@Overridepublic String getFormattedValue(float value) {return super.getFormattedValue(value);} }); //設(shè)置x軸文字顏色 xAxis.setTextColor(Color.RED); //設(shè)置x軸最小刻度 interval 默認(rèn)1 xAxis.setGranularity(0.01f);示例-設(shè)置Y軸
YAxis yAxis = chart.getAxisLeft();yAxis.setAxisMaximum(200f); //一般情況都要設(shè)置 比如常見(jiàn)的yAxis.setAxisMinimum(0f);不設(shè)置可能出現(xiàn)柱子和x軸有偏移量 yAxis.setAxisMinimum(-50f); //設(shè)置不顯示此軸 yAxis.setDrawAxisLine(false); //設(shè)置不顯示右邊的y軸 chart.getAxisRight().setEnabled(false); //設(shè)置y軸數(shù)據(jù)標(biāo)簽相對(duì)圖表的位置 默認(rèn)在圖表外面 yAxis.setPosition(YAxis.YAxisLabelPosition.OUTSIDE_CHART); //設(shè)置顯示y軸零坐標(biāo)線 設(shè)置后零坐標(biāo)線會(huì)繪制成實(shí)線 yAxis.setDrawZeroLine(true); //設(shè)置y軸的文字顏色 yAxis.setTextColor(Color.GREEN); //設(shè)置y軸文字的大小 yAxis.setTextSize(12f); //設(shè)置y軸數(shù)據(jù)偏移量 yAxis.setXOffset(16f); //設(shè)置y軸label數(shù)量,并強(qiáng)制為5個(gè)(isforce=true時(shí),會(huì)根據(jù)數(shù)據(jù)計(jì)算label上的數(shù)值) yAxis.setLabelCount(5, true); //設(shè)置y軸的最小刻度 yAxis.setGranularity(5);MarkerView
可以理解為數(shù)據(jù)點(diǎn)的彈出框。
示例
值得注意,以下設(shè)置可能造成MarkerView不顯示
- 禁用了每次點(diǎn)擊突出顯示條目的功能
- ChartData設(shè)置禁用數(shù)據(jù)對(duì)象突出顯示值
如果只想突出顯示部分值,可以通過(guò)chart.highlightValue(…)手動(dòng)設(shè)置
補(bǔ)充:使用SpannableStringBuilder顯示不一樣的字體
public class MyMarkerXyView extends MarkerView {private final TextView tvContent;public MyMarkerXyView(Context context, int layoutResource) {super(context, layoutResource);tvContent = findViewById(R.id.tvContent);}@Overridepublic void refreshContent(Entry e, Highlight highlight) {ForegroundColorSpan colorSpanX = new ForegroundColorSpan(Color.RED);ForegroundColorSpan colorSpanY = new ForegroundColorSpan(Color.BLUE);SpannableStringBuilder ssbBuilder = new SpannableStringBuilder();ssbBuilder.append("●");ssbBuilder.setSpan(colorSpanX, 0, 1, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);ssbBuilder.append("X值:").append(String.valueOf(e.getX()));ssbBuilder.append("\n");int start = ssbBuilder.length();ssbBuilder.append("●");ssbBuilder.setSpan(colorSpanY, start, start + 1, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);ssbBuilder.append("Y值:").append(String.valueOf(e.getY()));tvContent.setText(ssbBuilder);super.refreshContent(e, highlight);}@Overridepublic MPPointF getOffset() {return new MPPointF(-(getWidth() / 2), -getHeight());} }問(wèn)題記錄
問(wèn)題1:無(wú)法在MPAndroidChart中設(shè)置Double值
不同于IOS版的此庫(kù)。Android端中有些庫(kù)(例如android.graphics.matrix)不支持double,這非常不幸。
我在使用3.1.0版的MPAndroidChart,Entry(x,y)都是float作為參數(shù),對(duì)于較大和較長(zhǎng)的數(shù)據(jù),會(huì)出現(xiàn)精度的丟失。
舉個(gè)例子,使用時(shí)間戳作為橫軸,因?yàn)閹?kù)中api方法都是傳float類(lèi)型的值,而float能保證精度有限(非指數(shù)部分只能容納23位信息,僅使用整數(shù),就會(huì)開(kāi)始看到超過(guò)16777216的精度損失)。所以使用時(shí)間戳作為坐標(biāo)的值,會(huì)有誤差,并且以軸的值作為參考設(shè)置的寬度等都會(huì)出現(xiàn)問(wèn)題,如坐標(biāo)顯示與實(shí)際相差幾十秒、圖發(fā)生偏移等。如圖所示:
問(wèn)題2:ValueFormatter處出錯(cuò)ArrayIndexOutOfBoundsException
常見(jiàn)于只有一條數(shù)據(jù)的時(shí)候,會(huì)出現(xiàn)比如-1這樣的value,需要處理
//list是接口獲取的數(shù)據(jù)bean列表for (i in list.indices) {values.add(Entry(i.toFloat(), list[i].number.toFloat(), null))} chart.xAxis.valueFormatter = object : ValueFormatter() {override fun getFormattedValue(value: Float): String {if (value.toInt() < 0 || value.toInt() >= list.size) {return ""}//顯示這條數(shù)據(jù)的時(shí)間字段return list[value.toInt()].dataTime} }AAChart
這個(gè)庫(kù)也很好用:AAChartCore-Kotlin,做柱狀圖、玫瑰圖啥的。
后話(huà)
如果圖表不顯示,手動(dòng)validate一下,還不顯示,查數(shù)據(jù)源和設(shè)置的問(wèn)題。
總結(jié)
以上是生活随笔為你收集整理的MPAndroidChart使用记录的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 商用DCLS双核锁步lockstep技术
- 下一篇: 芯片里的SOP SSOP TSOP TS