日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > Android >内容正文

Android

MPAndroidChart使用记录

發(fā)布時(shí)間:2024/1/1 Android 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MPAndroidChart使用记录 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

    • 前言
    • 舉例說(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(); // refresh

    ComponentBase

    看了以下發(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)段偽代碼

    LegendEntry legendEntryA = new LegendEntry(); legendEntryA.label = "labelName-A"; legendEntryA.formColor = Color.GREEN;

    然后通過(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)足要求,還是拉源碼去改吧。

    /*** Should the legend word wrap? / this is currently supported only for:* BelowChartLeft, BelowChartRight, BelowChartCenter. / note that word* wrapping a legend takes a toll on performance. / you may want to set* maxSizePercent when word wrapping, to set the point where the text wraps.* / default: false** @param enabled*/public void setWordWrapEnabled(boolean enabled) {mWordWrapEnabled = enabled;}

    示例

    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)的彈出框。

  • 繼承MarkerView 實(shí)現(xiàn)一個(gè)自定義View
  • 將chart和markerview綁定起來(lái)
  • 示例

  • 布局
  • <?xml version="1.0" encoding="utf-8"?> <androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="wrap_content"android:layout_height="40dp"app:cardBackgroundColor="@android:color/holo_orange_light"xmlns:app="http://schemas.android.com/apk/res-auto"app:cardCornerRadius="4dp"tools:ignore="Overdraw"><TextViewandroid:id="@+id/tvContent"android:layout_width="wrap_content"android:layout_height="match_parent"android:layout_marginLeft="16dp"android:layout_marginRight="16dp"android:layout_marginTop="8dp"android:layout_marginBottom="8dp"android:gravity="center_vertical"android:text=""android:textSize="12sp"android:textColor="@android:color/black"android:ellipsize="end"android:singleLine="true"android:textAppearance="?android:attr/textAppearanceSmall" /></androidx.cardview.widget.CardView>
  • 自定義MarkerView
  • @SuppressLint("ViewConstructor") public class MyMarkerView extends MarkerView {private final TextView tvContent;public MyMarkerView(Context context, int layoutResource) {super(context, layoutResource);tvContent = findViewById(R.id.tvContent);}@Overridepublic void refreshContent(Entry e, Highlight highlight) {//每個(gè)點(diǎn)都有一個(gè)水表信息,通過(guò)Entry獲取WaterInfo waterInfo=(WaterInfo)e.getData();if (waterInfo!=null){tvContent.setText(e.getData().toString());}super.refreshContent(e, highlight);}@Overridepublic MPPointF getOffset() {return new MPPointF(-(getWidth() / 2), -getHeight());} }
  • 最后設(shè)置一下
  • MyMarkerView mv = new MyMarkerView(this, R.layout.custom_marker_view); mv.setChartView(chart); chart.setMarker(mv);

    值得注意,以下設(shè)置可能造成MarkerView不顯示

    • 禁用了每次點(diǎn)擊突出顯示條目的功能
    chart.setHighlightPerTapEnabled(false);
    • ChartData設(shè)置禁用數(shù)據(jù)對(duì)象突出顯示值
    ChartData#setHighlightEnabled(false);

    如果只想突出顯示部分值,可以通過(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)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。