在 android开源图表库MPAndroidChart文档翻译(上) 中,介绍了mpandroidchart的创建,回调方法,还有轴。这篇文章继续翻译剩余内容。文档内容比较多,这是中篇。最后的内容在下篇做翻译。

六、设置数据

要给图表设置数据,调用的方法为


public void setData(ChartData data) { ... }



ChartData是渲染过程中所需图表所有数据和信息的基类。对于每种图表,有不同的子类用来设置特定图表的数据。例如LineData。可以用ArrayList<? extends IDataSet> 作为展示数据,String类型的数组描述X轴标签。例如LineData用于将数据添加到线性图表。



// this is just one of many constructors
    public LineData(ArrayList<String> xVals, ArrayList<ILineDataSet> sets) { ... }



那么,什么事DataSet 呢?我们为什么需要它呢?很简单,每一个DataSet对象代表一组属于一个表的数据记录,它用来分离不同组的逻辑值,每种类型的图表对应不同DataSet的子类,对应不同样式。


例如,你可能想在LineChart中想展示两家公司一年的季度收入。这种情况,建议使用两个不同的LineDataSet对象,每个包含四个值(一年四个季度),使用ArrayList描述X轴上的标签,只需要简单数据源 "1.Q", "2.Q", "3.Q", "4.Q"。
当然,使用一个LineDataSet对象,包含这两个公司的8个值也是可以的。
初始化LineDataSet对象


public LineDataSet(ArrayList<Entry> yVals, String label) { ... }



通过构造方法可以发现,LinedDataSet需要一个Entry类型的ArrayList和一个字符串作为LineDtaSet的描述。此外,这个标签可以用来找到LineData对象中的LineDataSet对象集合


Entry类型的ArrayList包含了表中的所有值,一个Entry对象包含了x轴的位置,和它对应的值。


public Entry(float val, int xIndex) { ... }


全部放在一起(超过一年的两家公司的季度收入例子):

首先,创建Entry类型的list,来保存值


ArrayList<Entry> valsComp1 = new ArrayList<Entry>();
    ArrayList<Entry> valsComp2 = new ArrayList<Entry>();


然后,填充这些Enty对象值。确保对应对象包含正确x轴索引。 (当然,在这里可以使用一个循环,在这种情况下,循环的计数器变量可以是在x轴上的索引)。


Entry c1e1 = new Entry(100.000f, 0); // 0 == quarter 1
    valsComp1.add(c1e1);
    Entry c1e2 = new Entry(50.000f, 1); // 1 == quarter 2 ...
    valsComp1.add(c1e2);
    // and so on ...

    Entry c2e1 = new Entry(120.000f, 0); // 0 == quarter 1
    valsComp2.add(c2e1);
    Entry c2e2 = new Entry(110.000f, 1); // 1 == quarter 2 ...
    valsComp2.add(c2e2);
    //...


这个时候,已经创建好了Entry对象的list,可以创建LineDataSet对象了


LineDataSet setComp1 = new LineDataSet(valsComp1, "Company 1");
 setComp1.setAxisDependency(AxisDependency.LEFT);
 LineDataSet setComp2 = new LineDataSet(valsComp2, "Company 2");
 setComp2.setAxisDependency(AxisDependency.LEFT);


通过调用setAxisDependency,DataSet轴中应该对指定绘制,最后异步,但是重要,我们创建IDataSets 列表和x轴条目列表,并建立我们的ChartData对象:


// use the interface ILineDataSet
    ArrayList<ILineDataSet> dataSets = new ArrayList<ILineDataSet>();
    dataSets.add(setComp1);
    dataSets.add(setComp2);

    ArrayList<String> xVals = new ArrayList<String>();
    xVals.add("1.Q"); xVals.add("2.Q"); xVals.add("3.Q"); xVals.add("4.Q"); 

    LineData data = new LineData(xVals, dataSets);
    mLineChart.setData(data);
    mLineChart.invalidate(); // refresh


调用invalidate之后,表会刷新,提供的数据会重绘

七、设置颜色


自发布V1.4.0之后,早期版本ColorTemplate对象不再需要,ColorTemplate负责在以前的版本设置颜色。尽管如此,它仍持有所有预定义的色彩阵列(例如ColorTemplate.VORDIPLOM_COLORS并提供从资源(资源整数)到“真正的”色色转换方便的方法。

代替ColorTemplate,颜色现在可以直接通过数据集对象设置,这允许每个数据集单独造型指定。

例如,我们有一个代表两个公司(以前在设置数据教程中提到的),为此,我们现在要设置不同的颜色的季度收入我们的两个不同的LineDataSet对象。

我们希望用红色代表一个公司的数据
用绿色代表另一个公司数据。
代码为


LineDataSet setComp1 = new LineDataSet(valsComp1, "Company 1");
  // sets colors for the dataset, resolution of the resource name to a "real" color is done internally
  setComp1.setColors(new int[] { R.color.red1, R.color.red2, R.color.red3, R.color.red4 }, Context);

  LineDataSet setComp2 = new LineDataSet(valsComp2, "Company 2");
  setComp2.setColors(new int[] { R.color.green1, R.color.green2, R.color.green3, R.color.green4 }, Context);


setColors(int [] colors, Context c): 通过color资源id设置颜色

setColors(int [] colors):通过真实色值的数组来设置颜色

setColors(ArrayList<Integer> colors)通过真实色值的list来设置颜色

setColor(int color): 设置为同一个颜色

ColorTemplate 的例子:


LineDataSet set = new LineDataSet(...);
set.setColors(ColorTemplate.VORDIPLOM_COLORS);


没有设置颜色,使用默认值。


八、值的格式化接口ValueFormatter

从1.6.2版本可用,在2.1.4版本做出修改。
ValueFormatter接口可以用来指定绘制的格式


ublic class MyValueFormatter implements ValueFormatter {

    private DecimalFormat mFormat;

    public MyValueFormatter() {
        mFormat = new DecimalFormat("###,###,##0.0"); // use one decimal
    }

    @Override
    public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) {
        // write your logic here
        return mFormat.format(value) + " $"; // e.g. append a dollar-sign
    }
}


使用


// usage on whole data object
lineData.setValueFormatter(new MyValueFormatter());

// usage on individual dataset object
lineDataSet.setValueFormatter(new MyValueFormatter());


预定义的格式

LargeValueFormatter: 用于较大值得转换,如1000转换成1k,不支持小数点。
PercentFormatter:使用百分号,在饼状图中特别有用
StackedValueFormatter: 在 BarChart中使用. 它允许指定所有的堆栈值是否应绘制,或者是最高值

九、X轴上的格式化接口XAxisValueFormatter

2.1.4版本之后可用。


XAxisValueFormatter接口可以动态调整X值得显示方式。



public class MyCustomXAxisValueFormatter implements XAxisValueFormatter {

    @Override
    public String getXValue(String original, int index, ViewPortHandler viewPortHandler) {
        // original is the original value to use, x-index is the index in your x-values array
        // implement your logic here ...
        return ...;
    }
}



使用


// usage on XAxis, get axis instance:
XAxis xAxis = chart.getXAxis();

// set the formatter
xAxis.setValueFormatter(new MyCustomXAxisValueFormatter());



预定义格式转换DefaultXAxisValueFormatter

自定义格式转换MyCustomXValueFormatter


十、Y轴上的格式化接口YAxisValueFormatter


与XAxisValueFormatter类似


public class MyYAxisValueFormatter implements YAxisValueFormatter {

    private DecimalFormat mFormat;

    public MyYAxisValueFormatter () {
        mFormat = new DecimalFormat("###,###,##0.0"); // use one decimal
    }

    @Override
    public String getFormattedValue(float value, YAxis yAxis) {
        // write your logic here
        // access the YAxis object to get more information
        return mFormat.format(value) + " $"; // e.g. append a dollar-sign
    }
}


设置


// get an instance of the YAxis (e.g. left axis)
YAxis leftAxis = chart.getAxisLeft();
leftAxis.setValueFormatter(new MyYAxisValueFormatter());



十一、具体图表的设置

Line-, Bar-, Scatter-, Candle- & BubbleChart

折线图,条形表,散点图,K线图,气泡图

setAutoScaleMinMaxEnabled(boolean enabled): 指示是否启用在y轴自动缩放。如果启用,当视角变换时,Y轴自动调整到和当前的X轴范围适应的最小值,默认值false
setKeepPositionOnRotation(boolean enabled): 伸缩之后是否能还原到原来的位置. 默认值false

BarChart条形图

setDrawValueAboveBar(boolean enabled): 如果设置为true,在条形图上方显示值。如果为false,会显示在顶部下方。
 setDrawBarShadow(boolean enabled): 是否显示阴影。启动它会降低约40%的性能
 setDrawValuesForWholeStack(boolean enabled): 如果设置为true,堆叠条形的所有值会分别绘制,而不仅仅是他们所有的顶部总和。
 setDrawHighlightArrow(boolean enabled): 是否强调绘制箭头


PieChart饼状图


setDrawSliceText(boolean enabled): 设置为true,x轴文字会绘制为扇形
 setUsePercentValues(boolean enabled): 如果启用,图表内值以百分比绘制。
 setCenterText(SpannableString text): 设置中心文本,较长的文字会被调整,避免剪裁
 setCenterTextRadiusPercent(float percent): 文本中心边框的矩形半径,默认1.0f
 setHoleRadius(float percent): 设置在饼图中心的最大半径。默认50%
 setTransparentCircleRadius(float percent): setTransparentCircleAlpha(int alpha): 设置透明度,0-255
 setMaxAngle(float maxangle):设置最大角度,默认360f


RadarChart雷达图


setSkipWebLineCount(int count): 允许跳过图表中心网状线,如果有很多行驶很有用的


十二、图例


默认情况下,所有图表都会自动生成图例。图例通常由一个标签的形式来表示每一个条目


自动生成的图例包含条目的数量取决于不同颜色的数量以及关于数据集的标签。如果多种颜色用于一个数据集,这些颜色只属于一个标签。定制图例首先要获取图例


Legend legend = chart.getLegend();



设置图例是否被绘制

setEnabled(boolean enabled)



设置图例颜色、位置、标签、字体

Legend l = chart.getLegend();
    l.setFormSize(10f); // set the size of the legend forms/shapes
    l.setForm(LegendForm.CIRCLE); // set what type of form/shape should be used
    l.setPosition(LegendPosition.BELOW_CHART_LEFT);
    l.setTypeface(...);
    l.setTextSize(12f);
    l.setTextColor(Color.BLACK);
    l.setXEntrySpace(5f); // set the space between the legend entries on the x-axis
    l.setYEntrySpace(5f); // set the space between the legend entries on the y-axis

    // set custom labels and colors
    l.setCustom(ColorTemplate.VORDIPLOM_COLORS, new String[] { "Set1", "Set2", "Set3", "Set4", "Set5" });

    // and many more...

十三、动态修改数据


为了动态增加新数据或者删除数据,需要有多种方法来增加或者删除实体对象。


DataSet 类和它的所有子类
addEntry(Entry e):增加新的Entry对象
ChartData 类和它的所有子类
addEntry(Entry e, int dataSetIndex): 在datasetindex这个位置添加新的Entry对象
addDataSet(DataSet d): 在现有的CharData上增加新的DataSet
删除操作

Class DataSet:
 public boolean removeFirst()
 public boolean removeLast()
 public boolean removeEntry(Entry e)
 public boolean removeEntry(int xIndex)
 Class ChartData:
 public boolean removeEntry(Entry e, int dataSetIndex)
 public boolean removeEntry(int xIndex, int dataSetIndex)
 public boolean removeDataSet(DataSet d)
 public boolean removeDataSet(int index)


注意,在动态修改数据之后,一定要在刷新之前调用notifyDataSetChanged()

moveViewTo(...)方法会自动调用刷新方法 invalidate().



// EXAMPLE 1
 // add entries to the "data" object
 exampleData.addEntry(...);
 chart.notifyDataSetChanged(); // let the chart know it's data changed
 chart.invalidate(); // refresh

 // EXAMPLE 2
 // add entries to "dataSet" object
 dataSet.addEntry(...);
 exampleData.notifyDataChanged(); // let the data know a dataSet changed
 chart.notifyDataSetChanged(); // let the chart know it's data changed
 chart.invalidate(); // refresh

示例

DynamicalAddingActivityRealtimeDataActivity

十四、修改视图窗口

这个库有多种修改视图方法,需要注意的是,这些方法只适用于LineChart, BarChart, ScatterChart and CandleStickChart。
下面提到的方法是Chart类提供的方法,另一种方法是通过ViewPortHandler直接访问,但是这种方法只推荐熟悉API的高级用户使用。


请注意,所有修改视方法都需要设定数据后才能被图表被调用。

限制可见性

setVisibleXRangeMaximum(float maxXRange): 设置X轴上可见区域的最大值。
 setVisibleXRangeMinimum(float minXRange):设置X轴上可见的最小值,限制最小缩放。
 setVisibleYRangeMaximum(float maxYRange, AxisDependency axis): 设置Y轴可见的最大值。
 setViewPortOffsets(float left, float top, float right, float bottom): 设置视图偏移量,影响自动偏移量,使用resetViewPortOffsets()方法撤销操作
 etExtraOffsets(float left, float top, float right, float bottom):设置额外的偏移量,这样做不会改变自动偏移量

移动视图

fitScreen(): 充满边界
 moveViewToX(float xValue):移动到X轴固定位置
 moveViewTo(float xValue, float yValue, AxisDependency axis): 移动到X,Y轴固定位置


移动动画设置
moveViewToAnimated(float xValue, float yValue, AxisDependency axis, long duration)
centerViewToAnimated(float xValue, float yValue, AxisDependency axis, long duration)
注意:所有的moveViewTo方法都会自动刷新视图,不需要调用invalidate()方法
缩放
zoomIn()
zoomOut():
zoom(float scaleX, float scaleY, float x, float y): 
zoom(float scaleX, float scaleY, float xValue, float yValue, AxisDependency axis): 
缩放动画
zoomAndCenterAnimated(float scaleX, float scaleY, float xValue, float yValue, AxisDependency axis, long duration):


chart.setData(...); // first set data

// now modify viewport
chart.setVisibleXRangeMaximum(20); // allow 20 values to be displayed at once on the x-axis, not more
chart.moveViewToX(10); // set the left edge of the chart to x-index 10
// moveViewToX(...) also calls invalidate()

十五、动画设置


注意:图表的动画只对API级别11(的Android3.0.x中)及更高版本才支持。低版本不会执行,也不会崩溃。


分别在X轴和Y轴应用动画


动画代码示例


mChart.animateX(3000); // animate horizontal 3000 milliseconds
// or:
mChart.animateY(3000); // animate vertical 3000 milliseconds
// or:
mChart.animateXY(3000, 3000); // animate horizontal and vertical 3000 milliseconds


如果调用那个了animate(...) 方法, 不需要调用 invalidate() 就可以刷新图表

动画设置

public enum EasingOption {
      Linear,
      EaseInQuad,
      EaseOutQuad,
      EaseInOutQuad,
      EaseInCubic,
      EaseOutCubic,
      EaseInOutCubic,
      EaseInQuart,
      EaseOutQuart,
      EaseInOutQuart,
      EaseInSine,
      EaseOutSine,
      EaseInOutSine,
      EaseInExpo,
      EaseOutExpo,
      EaseInOutExpo,
      EaseInCirc,
      EaseOutCirc,
      EaseInOutCirc,
      EaseInElastic,
      EaseOutElastic,
      EaseInOutElastic,
      EaseInBack,
      EaseOutBack,
      EaseInOutBack,
      EaseInBounce,
      EaseOutBounce,
      EaseInOutBounce,
  }



使用方法



public void animateY(int durationmillis, EasingFunction function);


自定义动画设置实现接口

/**
  * Interface for creating custom made easing functions. 
  */
  public interface EasingFunction {
     /**
      * Called everytime the animation is updated.
      * @param input - the time passed since the animation started (value between 0 and 1)
      */
      public float getInterpolation(float input);
  }



十六、MarkerView(浮层)




继承MarkerView ,实现自定义弹出浮层。

调用setMarkerView(MarkerView mv)方法设置浮层

getMarkerView()获取浮层


public class CustomMarkerView extends MarkerView {

    private TextView tvContent;

    public CustomMarkerView (Context context, int layoutResource) {
        super(context, layoutResource);
        // this markerview only displays a textview
        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) {
        tvContent.setText("" + e.getVal()); // set the entry-value as the display text
    }

    @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();
    }
}


使用


CustomMarkerView mv = new CustomMarkerView(Context, R.layout.custom_marker_view_layout);

// set the marker to the chart
chart.setMarkerView(mv);