基于MPAndroidChart庫(kù)制作K線(xiàn)圖

最近制作一個(gè)炒幣的app,類(lèi)似于炒股的那種,網(wǎng)上資料很多很雜,最后使用github上面的MPAndroidChart庫(kù)基本實(shí)現(xiàn)了功能物邑。

一、介紹

MPAndroidChart庫(kù):https://github.com/PhilJay/MPAndroidChart

image

1.1支持圖形

  • Line Chart 折線(xiàn)圖
  • Bar Chart 直方圖
  • Pie Chart 餅圖
  • Bubble Chart 氣泡圖
  • Candle Stick Chart 蠟燭圖(用于展示金融數(shù)據(jù)時(shí)常稱(chēng)為K線(xiàn)圖)
  • Radar Chart 雷達(dá)圖
  • Cubic Line Chart 立方折線(xiàn)圖
  • Stacked Bar Chart 堆積圖

1.2MPAndroid使用

  • Project level build.gradle
allprojects {
    repositories {
        maven { url 'https://jitpack.io' }
    }
}
  • App level build.gradle
dependencies {
    implementation 'com.github.PhilJay:MPAndroidChart:v3.0.3'
}

二、基礎(chǔ)實(shí)現(xiàn)效果圖

基礎(chǔ)實(shí)現(xiàn)效果圖

三、核心代碼

3.1那先、初始化表格

主要的一些屬性均已寫(xiě)注釋,部分注釋可能有所偏差,具體以MPAndroidChart源碼注釋為準(zhǔn)

private void initChart() {
    //K線(xiàn)
    ccKl.setNoDataTextColor(getResources().getColor(R.color.gray8B));//無(wú)數(shù)據(jù)時(shí)提示文字的顏色
    ccKl.setDescription(null);//取消描述
    ccKl.getLegend().setEnabled(false);//取消圖例
    ccKl.setDragDecelerationEnabled(false);//不允許甩動(dòng)慣性滑動(dòng)  和moveView方法有沖突 設(shè)置為false
    ccKl.setMinOffset(0);//設(shè)置外邊緣偏移量
    ccKl.setExtraBottomOffset(6);//設(shè)置底部外邊緣偏移量 便于顯示X軸
    ccKl.setScaleEnabled(false);//不可縮放
    ccKl.setAutoScaleMinMaxEnabled(true);//自適應(yīng)最大最小值
    ccKl.setDrawOrder(new CombinedChart.DrawOrder[]{CombinedChart.DrawOrder.CANDLE, CombinedChart.DrawOrder.LINE}); //繪制順序,先繪制條形再繪制條線(xiàn)
    
    //K線(xiàn) x軸
    XAxis xac = ccKl.getXAxis();
    xac.setPosition(XAxis.XAxisPosition.BOTTOM);
    xac.setGridColor(getResources().getColor(R.color.black3B));//網(wǎng)格線(xiàn)顏色
    xac.setTextColor(getResources().getColor(R.color.gray8B));//標(biāo)簽顏色
    xac.setTextSize(8);//標(biāo)簽字體大小
    xac.setAxisLineColor(getResources().getColor(R.color.black3B));//軸線(xiàn)顏色
    xac.disableAxisLineDashedLine();//取消軸線(xiàn)虛線(xiàn)設(shè)置
    xac.setAvoidFirstLastClipping(true);//避免首尾端標(biāo)簽被裁剪
    xac.setLabelCount(5, true);//強(qiáng)制顯示2個(gè)標(biāo)簽
    
    //K線(xiàn) 左Y軸
    YAxis axisLeft = ccKl.getAxisLeft();
    axisLeft.setPosition(YAxis.YAxisLabelPosition.INSIDE_CHART);      //標(biāo)簽顯示在內(nèi)側(cè);OUTSIDE_CHART外側(cè)
    axisLeft.setGridColor(getResources().getColor(R.color.black3B));  //網(wǎng)格顏色
    axisLeft.setTextColor(getResources().getColor(R.color.gray8B));   //文字顏色
    axisLeft.setTextSize(8);  //文字大小
    axisLeft.setLabelCount(5, true);  //label個(gè)數(shù),強(qiáng)制設(shè)置標(biāo)簽計(jì)數(shù)
    axisLeft.enableGridDashedLine(5, 4, 0);//橫向網(wǎng)格線(xiàn)設(shè)置為虛線(xiàn)
    
    //K線(xiàn) 右Y軸
    YAxis axisRight = ccKl.getAxisRight();
    //axisRight.setEnabled(false);         //不繪制右軸
    axisRight.setDrawLabels(false);      //不繪制右軸標(biāo)簽
    axisRight.setDrawGridLines(false);   //不繪制網(wǎng)格
    axisRight.setDrawAxisLine(false);    //不繪制沿軸線(xiàn)
    
    //蠟燭圖
    candleSet = new CandleDataSet(new ArrayList<CandleEntry>(), "Kline");
    candleSet.setAxisDependency(YAxis.AxisDependency.LEFT);
    candleSet.setDrawHorizontalHighlightIndicator(false);
    candleSet.setHighlightLineWidth(0.5f);
    candleSet.setHighLightColor(getResources().getColor(R.color.brown));
    candleSet.setShadowWidth(0.7f);
    candleSet.setIncreasingColor(getResources().getColor(R.color.redEB)); //上漲設(shè)置為紅色
    candleSet.setIncreasingPaintStyle(Paint.Style.FILL);   //fill:實(shí)心填充  stroke:空心描邊  fill_and_stroke  填充描邊
    candleSet.setDecreasingColor(getResources().getColor(R.color.green4C));//下跌設(shè)置為綠色
    candleSet.setDecreasingPaintStyle(Paint.Style.FILL);   //fill:實(shí)心填充  stroke:空心描邊  fill_and_stroke  填充描邊
    candleSet.setNeutralColor(getResources().getColor(R.color.redEB));
    candleSet.setShadowColorSameAsCandle(true);
    candleSet.setDrawValues(false);
    candleSet.setHighlightEnabled(false);
    //5分均線(xiàn)
    lineSet5 = new LineDataSet(new ArrayList<Entry>(), "MA5");
    lineSet5.setAxisDependency(YAxis.AxisDependency.LEFT);
    lineSet5.setColor(getResources().getColor(R.color.purple));
    lineSet5.setDrawCircles(false);
    lineSet5.setDrawValues(false);
    lineSet5.setHighlightEnabled(false);
    //10分均線(xiàn)
    lineSet10 = new LineDataSet(new ArrayList<Entry>(), "MA10");
    lineSet10.setAxisDependency(YAxis.AxisDependency.LEFT);
    lineSet10.setColor(getResources().getColor(R.color.yellow));
    lineSet10.setDrawCircles(false);
    lineSet10.setDrawValues(false);
    lineSet10.setHighlightEnabled(false);
    //30分均線(xiàn)
    lineSet30 = new LineDataSet(new ArrayList<Entry>(), "MA30");
    lineSet30.setAxisDependency(YAxis.AxisDependency.LEFT);
    lineSet30.setColor(getResources().getColor(R.color.white));
    lineSet30.setDrawCircles(false);
    lineSet30.setDrawValues(false);
    lineSet30.setHighlightEnabled(false);
    //分時(shí)線(xiàn)
    lineSetMin = new LineDataSet(new ArrayList<Entry>(), "Minutes");
    lineSetMin.setAxisDependency(YAxis.AxisDependency.LEFT);
    lineSetMin.setColor(Color.WHITE);
    lineSetMin.setDrawCircles(false);
    lineSetMin.setDrawValues(false);
    lineSetMin.setDrawFilled(true);
    lineSetMin.setHighlightEnabled(false);
    lineSetMin.setFillColor(getResources().getColor(R.color.gray8B));
    lineSetMin.setFillAlpha(60);
    
    
    //成交量
    bcKl.setNoDataTextColor(getResources().getColor(R.color.gray8B));
    bcKl.setDescription(null);
    bcKl.getLegend().setEnabled(false);
    bcKl.setDragDecelerationEnabled(false);   //不允許甩動(dòng)慣性滑動(dòng)
    bcKl.setMinOffset(0);   //設(shè)置外邊緣偏移量
    bcKl.setScaleEnabled(false);//不可縮放
    bcKl.setAutoScaleMinMaxEnabled(true);//自適應(yīng)最大最小值
    //自定義Y軸標(biāo)簽位置
    bcKl.setRendererLeftYAxis(new InBoundYAxisRenderer(bcKl.getViewPortHandler(), bcKl.getAxisLeft(),
       bcKl.getTransformer(YAxis.AxisDependency.LEFT)));
    //設(shè)置渲染器控制顏色、偏移赡艰,以及高亮
    bcKl.setRenderer(new OffsetBarRenderer(bcKl, bcKl.getAnimator(), bcKl.getViewPortHandler(), -0.5f)
       .setHighlightWidthSize(0.5f, CommentUtil.sp2px(this, 8)));
    
    //x軸
    XAxis xAxis = bcKl.getXAxis();
    xAxis.setEnabled(false);
    
    //左Y軸
    YAxis axisLeft1 = bcKl.getAxisLeft();
    axisLeft1.setPosition(YAxis.YAxisLabelPosition.INSIDE_CHART);//標(biāo)簽顯示在內(nèi)側(cè)
    axisLeft1.setDrawAxisLine(false);
    axisLeft1.setGridColor(getResources().getColor(R.color.black3B));
    axisLeft1.setTextColor(getResources().getColor(R.color.gray8B));
    axisLeft1.setTextSize(8);
    axisLeft1.setLabelCount(2, true);
    axisLeft1.setAxisMinimum(0);
    axisLeft1.setValueFormatter(new IAxisValueFormatter() {
        @Override
        public String getFormattedValue(float value, AxisBase axis) {
           return value == 0 ? "" : value + "";
        }
    });
    
    //右Y軸
    YAxis axisRight1 = bcKl.getAxisRight();
    //axisRight1.setEnabled(false);         //不繪制右軸
    axisRight1.setDrawLabels(false);      //不繪制右軸標(biāo)簽
    axisRight1.setDrawGridLines(false);   //不繪制網(wǎng)格
    axisRight1.setDrawAxisLine(false);    //不繪制沿軸線(xiàn)
    
    //柱狀圖
    barSet = new BarDataSet(new ArrayList<BarEntry>(), "VOL");
    barSet.setHighLightColor(getResources().getColor(R.color.brown));
    barSet.setColors(getResources().getColor(R.color.redEB), getResources().getColor(R.color.green4C));
    barSet.setDrawValues(false);
    barSet.setHighlightEnabled(false);
}

3.2售淡、數(shù)據(jù)來(lái)源以及設(shè)置數(shù)據(jù)

private void configData() {
      
      if (combinedData == null) {
          combinedData = new CombinedData();
      }
      xValues.clear();
      List<CandleEntry> candleValues = candleSet.getValues();
      candleValues.clear();
      List<Entry> ma5Values = lineSet5.getValues();
      ma5Values.clear();
      List<Entry> ma10Values = lineSet10.getValues();
      ma10Values.clear();
      List<Entry> ma30Values = lineSet30.getValues();
      ma30Values.clear();
      List<Entry> minValues = lineSetMin.getValues();
      minValues.clear();
      List<BarEntry> barValues = barSet.getValues();
      barValues.clear();
      for (int i = 0; i < dataList.size(); i++) {
          List<String> k = dataList.get(i);
          Date d = new Date(Long.parseLong(k.get(6)) * 1000);     //6.毫秒
          String x = sdf.format(d);                               //顯示日期
          if (xValues.containsValue(x)) {                         //x重復(fù)
              dataList.remove(i);
              i--;
          } else {
              xValues.put(i, x);
              float open = Float.parseFloat(k.get(4));            //4.open
              float close = Float.parseFloat(k.get(1));           //1.close
              candleValues.add(new CandleEntry(i, Float.parseFloat(k.get(2)), Float.parseFloat(k.get(3)), open, close, x)); //2.max  3.min
              minValues.add(new Entry(i, close, x));
              barValues.add(new BarEntry(i, Float.parseFloat(k.get(8)), close >= open ? 0 : 1));  //8.volume交易量
              if (i >= 4) {
                  ma5Values.add(new Entry(i, getMA(i, 5)));
                  if (i >= 9) {
                      ma10Values.add(new Entry(i, getMA(i, 10)));
                      if (i >= 29) {
                          ma30Values.add(new Entry(i, getMA(i, 30)));
                      }
                  }
              }
          }
      }
      candleSet.setValues(candleValues);
      lineSet5.setValues(ma5Values);
      lineSet10.setValues(ma10Values);
      lineSet30.setValues(ma30Values);
      lineSetMin.setValues(minValues);

      if (tlKl.getSelectedTabPosition() == 0) {
          combinedData.removeDataSet(candleSet);                      //分時(shí)圖時(shí)移除蠟燭圖
          combinedData.setData(new LineData(lineSetMin));             //分時(shí)線(xiàn)
      } else {
          combinedData.setData(new CandleData(candleSet));            //蠟燭圖
          combinedData.setData(new LineData(lineSet5, lineSet10, lineSet30));    //5分線(xiàn) 10分線(xiàn) 30分線(xiàn)
      }

      ccKl.setData(combinedData);
      float xMax = xValues.size() - 0.5F;       //默認(rèn)X軸最大值是 xValues.size() - 1
      ccKl.getXAxis().setAxisMaximum(xMax);     //使最后一個(gè)顯示完整

      barSet.setValues(barValues);
      BarData barData = new BarData(barSet);
      barData.setBarWidth(1 - candleSet.getBarSpace() * 2);//使Candle和Bar寬度一致
      bcKl.setData(barData);
      bcKl.getXAxis().setAxisMaximum(xMax + (-0.5f));//保持邊緣對(duì)齊
      ccKl.setVisibleXRange(52, 52);//設(shè)置顯示X軸個(gè)數(shù)的上下限,豎屏固定52個(gè)
      bcKl.setVisibleXRange(52, 52);
      
 }

四、源碼下載

github: https://github.com/xkdaq/KoinChart

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末揖闸,一起剝皮案震驚了整個(gè)濱河市揍堕,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌汤纸,老刑警劉巖衩茸,帶你破解...
    沈念sama閱讀 219,188評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異贮泞,居然都是意外死亡楞慈,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)啃擦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)囊蓝,“玉大人,你說(shuō)我怎么就攤上這事议惰∩骺牛” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,562評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵言询,是天一觀的道長(zhǎng)俯萎。 經(jīng)常有香客問(wèn)我,道長(zhǎng)运杭,這世上最難降的妖魔是什么夫啊? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,893評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮辆憔,結(jié)果婚禮上撇眯,老公的妹妹穿的比我還像新娘。我一直安慰自己虱咧,他們只是感情好熊榛,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,917評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著腕巡,像睡著了一般玄坦。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上绘沉,一...
    開(kāi)封第一講書(shū)人閱讀 51,708評(píng)論 1 305
  • 那天煎楣,我揣著相機(jī)與錄音,去河邊找鬼车伞。 笑死择懂,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的另玖。 我是一名探鬼主播困曙,決...
    沈念sama閱讀 40,430評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼表伦,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了赂弓?” 一聲冷哼從身側(cè)響起绑榴,我...
    開(kāi)封第一講書(shū)人閱讀 39,342評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎盈魁,沒(méi)想到半個(gè)月后翔怎,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,801評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡杨耙,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,976評(píng)論 3 337
  • 正文 我和宋清朗相戀三年赤套,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片珊膜。...
    茶點(diǎn)故事閱讀 40,115評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡容握,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出车柠,到底是詐尸還是另有隱情剔氏,我是刑警寧澤,帶...
    沈念sama閱讀 35,804評(píng)論 5 346
  • 正文 年R本政府宣布竹祷,位于F島的核電站谈跛,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏塑陵。R本人自食惡果不足惜感憾,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,458評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望令花。 院中可真熱鬧阻桅,春花似錦、人聲如沸兼都。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,008評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)扮碧。三九已至趟章,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間芬萍,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,135評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工搔啊, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留柬祠,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,365評(píng)論 3 373
  • 正文 我出身青樓负芋,卻偏偏與公主長(zhǎng)得像漫蛔,于是被迫代替她去往敵國(guó)和親嗜愈。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,055評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容