当前位置: 移动技术网 > IT编程>移动开发>Android > Android实现价格走势自定义曲线图

Android实现价格走势自定义曲线图

2019年07月24日  | 移动技术网IT编程  | 我要评论

李伯伟,宋祖英小巨蛋,流氓公爵txt下载

本文是引用开源图表库框架 mpandroidchart的linechart

地址:https://github.com/philjay/mpandroidchart

1.需求:

(1)动态添加radiobutton,点击改变下面的linechart数据

(2)linechart绘制价格走势图,只显示最低点的小圆点和view,手指滑动,markview数据变化。

(3) 服务端返回端数据,不是每一天端数据,但是x轴显示的必须是每一天的数据,这里是有我自己处理过的。返回里需要显示点的数组,之前的时间点显示的就是第一个点值。

2.实现效果:

最低点显示view和小圆点是自定义的,通过修改 linechart的源码,下面我们来具体分析代码

3.代码分析

(1)布局的xml

<?xml version="1.0" encoding="utf-8"?>
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:orientation="vertical">

  <radiogroup
    android:id="@+id/mradiogroup"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_margintop="30px"
    android:orientation="horizontal"
    android:visibility="gone">
  </radiogroup>

  <linearlayout
    android:layout_width="match_parent"
    android:layout_height="200dp"
    android:orientation="vertical">

    <com.github.mikephil.charting.charts.linechart
      android:id="@+id/mlinechart"
      android:layout_width="match_parent"
      android:layout_height="0dp"
      android:layout_weight="1" />

    <linearlayout
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:orientation="horizontal">

      <textview
        android:id="@+id/detailmintimetv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginleft="50px"
        android:layout_weight="1"
        android:textcolor="#b5b5b5"
        android:textsize="24px" />

      <textview
        android:id="@+id/detailmaxtimetv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginright="30px"
        android:layout_weight="1"
        android:gravity="right"
        android:textcolor="#b5b5b5"
        android:textsize="24px" />
    </linearlayout>
  </linearlayout>
</linearlayout>

这里主要是添加以一个radiogroup和一个linechart

接下来是mainactivity.class

private void addviewforgroup(final list<jsondata.historicalprice> list) {
    for (int i = 0; i < list.size(); i++) {
      final radiobutton view = (radiobutton) layoutinflater.from(mainactivity.this)
          .inflate(r.layout.item_gr_add_but_layout, mradiogroup, false);
      view.setid(i);
      view.settext(list.get(i).gettitle());
      if (i==0){
        view.performclick();
        radiogrouptextchange(list.get(0).getdata(), list.get(0).gettitle());
        mlinecharwidget = new linechartwidget(mainactivity.this,
            list.get(0).getdata(), mlinechart, setminprice(list.get(0).getdata()));
      }
      mradiogroup.addview(view);

    }
    mradiogroup.setoncheckedchangelistener(new radiogroup.oncheckedchangelistener() {
      @override
      public void oncheckedchanged(radiogroup group, int checkedid) {
        radiobutton button = (radiobutton) findviewbyid(checkedid);
        button.settext(list.get(checkedid).gettitle());

        for (int i = 0; i < list.size(); i++) {
          if (button.gettext().tostring().equals(list.get(i).gettitle())) {
            radiogrouptextchange(list.get(i).getdata(), list.get(i).gettitle());
            if (mlinecharwidget == null) {
              mlinecharwidget = new linechartwidget(mainactivity.this,
                  list.get(i).getdata(), mlinechart, setminprice(list.get(i).getdata()));
            } else {
              mlinecharwidget.updatelinechar(list.get(i).getdata(), setminprice(list.get(i).getdata()));
            }

          }
        }
      }
    });
  }

注意:这里的linechartwidget是我自己封装的一个linechart,包括linechart初始化,数据的处理,已经手势的一些操作

简单的说一下思路,因为 linechart的x,y都是自定义的,但是我这里只自定义的y轴,是把x隐藏起来的,x轴只显示最开始的点和结束的点,所以我这里有点投机,自己设置点两个textview来显示的

linechart的点一设置都是统一所有点都设置的,但是需求上是得只在最低点显示,并还要绘制一个view先初始化 view,然后解析数据,

 jsondata jsondetail = new gson().fromjson(jsonstr.tostring(), new typetoken<jsondata>() {
    }.gettype());
    if (jsondetail.gethistorical_price() != null && jsondetail.gethistorical_price().size() > 0) {
      setgrouplay(jsondetail.gethistorical_price());
    }

再根据解析的数据动态添加radiobutton

初始化linechart

private void initlinechar() {
    list<jsondata.historicalprice.historicalpricedata.datalist> datalist
        = removeduplictedata(mhistoricalprice.getdata_list());
    //设置手势滑动事件
    mlinechar.setonchartgesturelistener(this);
    //设置数值选择监听
    mlinechar.setonchartvalueselectedlistener(this);
    //后台绘制
    mlinechar.setdrawgridbackground(false);
    //设置描述文本
    mlinechar.getdescription().setenabled(false);
    mlinechar.settouchenabled(true); // 设置是否可以触摸
    mlinechar.setdragenabled(true);// 是否可以拖拽
    mlinechar.setscalexenabled(true); //是否可以缩放 仅x轴
    mlinechar.setscaleyenabled(true); //是否可以缩放 仅y轴
    mlinechar.setpinchzoom(true); //设置x轴和y轴能否同时缩放。默认是否

    mlinechar.setdragdecelerationfrictioncoef(0.99f);
    mlinechar.getaxisright().setenabled(false);
    // 默认动画
    mlinechar.animatex(2500);

    setmakelist(removeduplictedata(datalist));
    initmark(makelist, long.valueof(mhistoricalprice.getstart_time()));
    initxaxis(datalist.size(), xaxisvaluesstr);
    inityaxis();
    initlegend();
    setlinechardata(makelist);
  }

设置markview

private void setmakelist(list<jsondata.historicalprice.historicalpricedata.datalist> datalist) {
    try {
      simpledateformat format = new simpledateformat("yyyy-mm-dd hh:mm:ss");
      date dbegin = format.parse(format.format(long.valueof(mhistoricalprice.getstart_time()) * 1000));
      date dend = format.parse(format.format(long.valueof(mhistoricalprice.getend_time()) * 1000));
      float prices = 0;
      list<date> listdate = getdatesbetweentwodate(dbegin, dend);
      if (datalist.size() >= listdate.size()) {
        makelist.clear();
        makelist.addall(datalist);
      } else {
        for (int i = 0; i < listdate.size(); i++) {
          jsondata.historicalprice.historicalpricedata.datalist data
              = new jsondata.historicalprice.historicalpricedata.datalist();
          for (int j = 0; j < datalist.size(); j++) {
            if (timetostring(datetotimestamp(listdate.get(i))).equals(timetostring(long.valueof(datalist.get(j).getprice_drop_time())))) {
              data.setprice_drop_time(datalist.get(j).getprice_drop_time());
              data.setprice_new(datalist.get(j).getprice_new());
              prices = (datalist.get(j).getprice_new());

            } else {
              data.setprice_drop_time(datetotimestamp(listdate.get(i)) + "");
              data.setprice_new(prices);
            }
          }
          makelist.add(data);
        }
      }


    } catch (parseexception e) {
      e.printstacktrace();
    }

  }

这里是设置linechart里面的数据

private void setdata(arraylist<entry> values) {
    linedataset set1 = null;
    if (mlinechar.getdata() != null && mlinechar.getdata().getdatasetcount() > 0) {
      set1 = (linedataset) mlinechar.getdata().getdatasetbyindex(0);
      set1.setvalues(values);
      mlinechar.getdata().notifydatachanged();
      mlinechar.notifydatasetchanged();
    } else {
      // 创建一个数据集,并给它一个类型
      if (set1 == null) {
        set1 = new linedataset(values, "价格曲线图");
        set1.setcolor(color.rgb(27, 198, 181));
        set1.setcirclecolor(color.black);
        set1.setlinewidth(1f);
        set1.setcircleradius(3f);
        set1.setdrawcirclehole(false);
        set1.setvaluetextsize(9f);
        set1.setdrawfilled(true);
        set1.setformlinewidth(1f);
        set1.setformlinedasheffect(new dashpatheffect(new float[]{10f, 5f}, 0f));
        set1.sethighlightenabled(true); //允许突出显示dataset
        set1.setdrawhighlightindicators(false); // 取消点击线上的点展示十字标识
        set1.setdrawvalues(true); // 不展示线上面点的值
        //是否显示小圆点
        set1.setdrawcircles(false);
        //修改源码 自定义的参数,可以显示最低点的view
        set1.setlowdrawcircles(true);
        set1.setcirclecolors(color.rgb(27, 198, 181));//27, 198, 181
        //顶点设置值
        set1.setdrawvalues(false);
        set1.setfillcolor(color.rgb(203, 242, 238));
      }
      //修改源码 自定义的参数,可以显示最低点的view
      set1.setlownumbers(mindata);
      arraylist<ilinedataset> datasets = new arraylist<ilinedataset>();
      //添加数据集
      datasets.add(set1);
      //创建一个数据集的数据对象
      linedata data = new linedata(datasets);
      //设置数据
      mlinechar.setdata(data);
    }
  }

这里是在源码里新加的地方

 //修改源码 自定义的参数,可以显示最低点的view   
 set1.setlowdrawcircles(true);  
 set1.setlownumbers(mindata);

源码修改部分:

1.在linedataset添加2个参数,复写ilinedataset新加的方法

 //是否显示最低点的小圆点

 private boolean mdrawlowcircle = false;

 //最低点对应的具体值

 private float mlownumbers = 100f;

2.在ilinedataset接口中添加2个方法

boolean islowdrawcirclesenabled();

float getlownumbers();

3.修改源码linechartrenderer这个类的 drawvalues(canvas c)方法中,这里是设置最低点显示的view,这个方法中添加判断:

//设置最低点显示的自定义view
if (dataset.islowdrawcirclesenabled()) {
  if (entry.gety() == dataset.getymin()) {
    //设置在左边
    if (x < 100) {
      locationcode = 1;
    } else {  // 默认在右边
      locationcode = 0;
    }
    appcustomdrawvalue(c, dataset.getvalueformatter(), entry.gety(), entry, i, x,
        y - valoffset, color.white);
    break;
  }
}

private int locationcode = 0;
//设置最低点显示的text和text的背景框
private void appcustomdrawvalue(canvas c, ivalueformatter formatter, float value, entry entry, int datasetindex, float x, float y, int color) {

    // paint.fontmetrics fm = new paint.fontmetrics();
    mvaluepaint.setcolor(color.rgb(27, 198, 181));
    // mvaluepaint.getfontmetrics(fm);
    y = (y + utils.convertdptopixel(30));
    switch (locationcode) {
      case 0:
        rectf rectf = new rectf((x - utils.convertdptopixel(35)), (y - utils.convertdptopixel(23)),
            (x + utils.convertdptopixel(5)), y);
        c.drawroundrect(rectf, 10, 10, mvaluepaint);
        mvaluepaint.setcolor(color);
        c.drawtext("¥" + formatter.getformattedvalue(value, entry, datasetindex, mviewporthandler), x - utils.convertdptopixel(15), y - utils.convertdptopixel(10), mvaluepaint);
        break;
      case 1:
        rectf rectf1 = new rectf(x + utils.convertdptopixel(5), (y - utils.convertdptopixel(23)), x + utils.convertdptopixel(45), y);
        c.drawroundrect(rectf1, 10, 10, mvaluepaint);
        mvaluepaint.setcolor(color);
        c.drawtext("¥" + formatter.getformattedvalue(value, entry, datasetindex, mviewporthandler), x + utils.convertdptopixel(27), y - utils.convertdptopixel(10), mvaluepaint);
        break;
    }
  }

在drawcircles(canvas c)方法中添加判断:则可以显示最低点的小圆点了。

//显示最低点的小圆点
if (dataset.islowdrawcirclesenabled()) {
  if (e.gety() == dataset.getymin()) {
    bitmap circlebitmap = imagecache.getbitmap(j);
    c.drawbitmap(circlebitmap, mcirclesbuffer[0] - circleradius, mcirclesbuffer[1] - circleradius, null);
    break;

  }

}

好了,所有功能的关键部分已经讲完了。大家不懂的可以留言提问,或者自己下载源码看看:

github项目地址:https://github.com/songyan992/linechartstudy

源码下载地址:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网