Description
a. text displayed on the histogram
b. discontinuous Histogram display
Prototype follows:
Difficulties Description:
MPAndroidChart does not support text description information to the histogram display (bar graph); and the display node does not support pillar starting from 0.
The desired goals:
Code
Note implement this code only for the histogram (BarChart)
Draw a bar graph break
Description of the histogram is described by four coordinate buffer array Barbuffer object of the four elements (left, top, right, bottom ).
In MPAndroidChart, set BarChartEntry time, each float value corresponds to a histogram by region, i.e. a continuous buffer conversion element array (shown below). To describe the histogram is now interrupted, two float values (start, detaY). It is necessary to change the mapping of the corresponding array element feed (IBarDataSet data).
@Override
public void feed(IBarDataSet data) {
float size = data.getEntryCount() * phaseX;
float barWidthHalf = mBarWidth / 2f;
for (int i = 0; i < size; i++) {
BarEntry e = data.getEntryForIndex(i);
if(e == null)
continue;
float x = e.getX();
float y = e.getY();
float[] vals = e.getYVals();
if (!mContainsStacks || vals == null) {
...
} else {
float posY = 0f;
float negY = -e.getNegativeSum();
float yStart = 0f;
if(e.isPresentOneData()){
checkData(vals);
}
// fill the stack
for (int k = 0; k < vals.length; k++) {
float value = vals[k];
if (value == 0.0f && (posY == 0.0f || negY == 0.0f)) {
// Take care of the situation of a 0.0 value, which overlaps a non-zero bar
y = value;
yStart = y;
} else if (value >= 0.0f) {
y = posY;
yStart = posY + value;
posY = yStart;
} else {
y = negY;
yStart = negY + Math.abs(value);
negY += Math.abs(value);
}
float left = x - barWidthHalf;
float right = x + barWidthHalf;
float bottom, top;
if (mInverted) {
bottom = y >= yStart ? y : yStart;
top = y <= yStart ? y : yStart;
} else {
top = y >= yStart ? y : yStart;
bottom = y <= yStart ? y : yStart;
}
// multiply the height of the rect with the phase
top *= phaseY;
bottom *= phaseY;
//两个float元素对应一个 bar区域
if(k==0&&e.isPresentOneData()){
}else{
addBar(left, top, right, bottom);
}
}
}
}
reset();
}
Draw text descriptions
Excellent MPAndroidChart design is very friendly. Set aside a drawExtras (Canvas c) interface DataRenderer interface that allows developers to customize the content. And the text displayed on the histogram, the business logic is implemented in the method.
This reference DrawValue conventional method, write a description of the function information
@Override
public void drawExtras(Canvas c) {
// if values are drawn
List<IBarDataSet> dataSets = mChart.getBarData().getDataSets();
final float valueOffsetPlus = Utils.convertDpToPixel(4.5f);
float posOffset = 0f;
for (int i = 0; i < mChart.getBarData().getDataSetCount(); i++) {
IBarDataSet dataSet = dataSets.get(i);
if (!dataSet.isDrawDesEnabled())
continue;
// apply the text-styling defined by the DataSet
applyDesTextStyle(dataSet);
// calculate the correct offset depending on the draw position of
// the value
float valueTextHeight = Utils.calcTextHeight(mDesPaint, "8");
posOffset = valueTextHeight + valueOffsetPlus;
// get the buffer
BarBuffer buffer = mBarBuffers[i];
MPPointF iconsOffset = MPPointF.getInstance(dataSet.getIconsOffset());
iconsOffset.x = Utils.convertDpToPixel(iconsOffset.x);
iconsOffset.y = Utils.convertDpToPixel(iconsOffset.y);
int bufferIndex = 0;
int index = 0;
while (index < dataSet.getEntryCount() * mAnimator.getPhaseX()) {
BarEntry entry = dataSet.getEntryForIndex(index);
float[] vals = entry.getYVals();
float x = (buffer.buffer[bufferIndex] + buffer.buffer[bufferIndex + 2]) / 2f;
int color = dataSet.getDesTextColor(index);
if (!mViewPortHandler.isInBoundsRight(x))
break;
if (!mViewPortHandler.isInBoundsY(buffer.buffer[bufferIndex + 3])
|| !mViewPortHandler.isInBoundsLeft(x))
continue;
//核心代码 如果开始描述文字的功能,则渲染文字
if (dataSet.isDrawDesEnabled()) {
//检查空间
if(buffer.buffer[bufferIndex+3]-buffer.buffer[bufferIndex+1]>4+posOffset){
drawDes(c, entry.getDes(), x, buffer.buffer[bufferIndex + 3] - posOffset,
color);
}else {
drawDes(c, entry.getDes(), x, buffer.buffer[bufferIndex + 3] +
posOffset,
color);
}
}
// draw stack values
bufferIndex = vals == null ? bufferIndex + 4 : bufferIndex + 4 * (entry.isPresentOneData()?1:vals.length);
index++;
}
MPPointF.recycleInstance(iconsOffset);
}
}
Handle touch events
In MPAndroidChart in, onTouch event will eventually be applied to Range objects. And when defining BarChartEntry, if passed in the Float [] array, each element will be converted to a Range object. However, intermittent but data is expressed, it is necessary to describe the two float a target range. Specific modifications are as follows:
use
//a.设置BarEntry的步骤
ArrayList<BarEntry> barEntries = new ArrayList<>();
//1.链式调用
//1.1 注意,在new float[]{ 0, 0.21111f }数组中,第一个元素代表柱状图的起始位置;
//第二个元素代码柱状图的高度值
barEntries.add(new BarEntry(1, new float[]{ 0, 0.21111f })
//2.设置是否是float[2] 展示一个数据
.setPresentOneData(true)
//3. 设置文本描述信息
.setmDes("12.3%"));
barEntries.add(new BarEntry(2,new float[]{0.11111f,0.3f})
.setPresentOneData(true)
.setmDes("12.3%"));
...
...
barEntries.add(new BarEntry(6, new float[]{1,1.3f})
.setPresentOneData(true)
.setmDes("12.3%"));
//b.设置BarDataSet的步骤
BarDataSet barDataSet = new BarDataSet(barEntries, "error times").setDrawDesEnable(true);
//设置描述字体的颜色
barDataSet.setmDesColor(Color.RED);