MPAndroidChart Weekly data - android

So I am trying to do a weekly chart with current weeks data vs previous weeks data using MPAndroidChart. I can do single bars just fine and everything lines up, but when I try to do multi bar groups it does the following.
Is there something else I need to be doing? I only have 2 bars per group for each day. Here is my current code:
BarData barDataPayments = new BarData(barDataSetCurrentWeek, barDataSetPrevWeek);
barChartPayments.setData(barDataPayments);
XAxis xAxisPayments = barChartPayments.getXAxis();
xAxisPayments.setValueFormatter(new IndexAxisValueFormatter(labelWeekdayNames));
xAxisPayments.setYOffset(5);
xAxisPayments.setPosition(XAxis.XAxisPosition.BOTTOM);
xAxisPayments.setLabelCount(labelWeekdayNames.size());
xAxisPayments.setGranularity(1f);
xAxisPayments.setCenterAxisLabels(false);
xAxisPayments.setDrawGridLines(false);
float groupSpace = 0.08f;
float barSpace = 0.03f;
float barWidth = 0.2f;
barDataPayments.setBarWidth(barWidth);
barChartPayments.getXAxis().setAxisMinimum(0);
barChartPayments.getXAxis().setAxisMaximum(0 + barChartPayments.getBarData().getGroupWidth(groupSpace, barSpace) * 14);
barChartPayments.groupBars(0, groupSpace, barSpace);
barChartPayments.invalidate();

here I have a snippet it may help you,
BarData barData = new BarData();
int i=10;
for (ExpenseData expenseData : results) {
List<BarEntry> barEntryList = new ArrayList<>();
barEntryList.add(new BarEntry(i, (float) expenseData.getBalance()));
BarDataSet barDataSet = new BarDataSet(barEntryList, expenseData.getCategory());
int rand = (int) (i*Math.random());
barDataSet.setBarBorderWidth(1);
barDataSet.setBarBorderColor(Color.rgb(rand,i*20,i));
barDataSet.setColor(Color.rgb(rand,i*20,i));
barData.addDataSet(barDataSet);
i+=10;
}
barChart.setData(barData);

So what I ended up having to do is manually set the data. It took a little tweaking to get it just how I wanted it, I am sure there is a more proper way, but so far this was the easiest way that I have currently found.
xAxisMiles.setYOffset(0); // <---- CHANGED TO ZERO
xAxisMiles.setPosition(XAxis.XAxisPosition.BOTTOM);
xAxisMiles.setLabelCount(labelWeekdayNames.size());
xAxisMiles.setGranularity(1f);
xAxisMiles.setCenterAxisLabels(true); // <---- SET TO TRUE
xAxisMiles.setDrawGridLines(false);
//IMPORTANT *****
barDataPayments.setBarWidth(0.40f);
barDataPayments.getXAxis().setAxisMinimum(0);
barDataPayments.getXAxis().setAxisMaximum(7);
barDataPayments.groupBars(0, 0.10f, 0.05f);
//***** IMPORTANT*/

Related

IndexAxisValueFormatter not working as expected

I'm using the MPAndroidChart to create a bar chart. My configurations:
<string-array name="months_initials">
<item>J</item>
<item>F</item>
<item>M</item>
<item>A</item>
<item>M</item>
<item>J</item>
<item>J</item>
<item>A</item>
<item>S</item>
<item>O</item>
<item>N</item>
<item>D</item>
</string-array>
...
String[] months = getResources().getStringArray(R.array.months_initials);
chart.getXAxis().setCenterAxisLabels(true);
chart.getXAxis().setLabelCount(months.length, true);
chart.getXAxis().setValueFormatter(new IndexAxisValueFormatter(months) {
#Override
public String getFormattedValue(float value, AxisBase axis) {
Timber.i("index = %s", value);
return super.getFormattedValue(value, axis);
}
});
index = 0.5
index = 1.5909091
index = 2.6818182
index = 3.7727275
index = 4.8636365
index = 5.9545455
index = 7.0454545
index = 8.136364
index = 9.227273
index = 10.318182
index = 11.409091
And this is the result:
Now, if I change it to: return super.getFormattedValue(value-0.5f, axis);
The result is:
Again, if I add another change: chart.getXAxis().setLabelCount(Integer.MAX_VALUE, true);
index = 0.5
index = 1.0
index = 1.5
index = 2.0
index = 2.5
index = 3.0
index = 3.5
index = 4.0
index = 4.5
index = 5.0
index = 5.5
index = 6.0
index = 6.5
index = 7.0
index = 7.5
index = 8.0
index = 8.5
index = 9.0
index = 9.5
index = 10.0
index = 10.5
index = 11.0
index = 11.5
index = 12.0
index = 12.5
The result is:
A bit "hammer time" but it would work for me, unfortunately the labels are not correctly centered.
So, what's happening here, what am I missing? How can I achieve my final result?
Thanks for your time.
ps: opened an issue too.
EDIT full setup code:
String[] months = getResources().getStringArray(R.array.months_initials);
BarChart chart = binding.barChart;
chart.setTouchEnabled(false);
chart.getDescription().setEnabled(false);
chart.getLegend().setEnabled(false);
chart.getAxisLeft().setEnabled(false);
chart.getAxisRight().setEnabled(false);
chart.getXAxis().setPosition(XAxis.XAxisPosition.BOTTOM);
chart.getXAxis().setDrawAxisLine(false);
chart.getXAxis().setDrawGridLines(false);
chart.getXAxis().setCenterAxisLabels(true);
chart.getXAxis().setLabelCount(Integer.MAX_VALUE, true);
chart.getXAxis().setValueFormatter(new IndexAxisValueFormatter(months) {
#Override
public String getFormattedValue(float value, AxisBase axis) {
Timber.i("index = %s", value);
return super.getFormattedValue(value - 0.5f, axis);
}
});
chart.getXAxis().setTextColor(ContextCompat.getColor(this, R.color.grey));
chart.getXAxis().setTextSize(12);
BarDataSet barData = new BarDataSet(data, "data");
barData.setColor(ContextCompat.getColor(this, R.color.chart_bar));
barData.setDrawValues(false);
ArrayList<IBarDataSet> dataSets = new ArrayList<>();
dataSets.add(barData);
binding.barChart.setData(new BarData(dataSets));
binding.barChart.animateY(1000, Easing.EasingOption.Linear);
I can't exactly pin point the issue in your code but it is probably something do with the granularity of the chart.
But here's a rough working example. Hope this helps!
String[] months = {"Jan", "Feb", "Mar", "Apr", "May", "Jun"};
BarChart mChart = (BarChart) findViewById(R.id.barChart);
mChart.setDrawBarShadow(false);
mChart.setDrawValueAboveBar(false);
mChart.getDescription().setEnabled(false);
mChart.setDrawGridBackground(false);
XAxis xaxis = mChart.getXAxis();
xaxis.setDrawGridLines(false);
xaxis.setPosition(XAxis.XAxisPosition.BOTTOM);
xaxis.setGranularity(1f);
xaxis.setDrawLabels(true);
xaxis.setDrawAxisLine(false);
xaxis.setValueFormatter(new IndexAxisValueFormatter(months));
YAxis yAxisLeft = mChart.getAxisLeft();
yAxisLeft.setPosition(YAxis.YAxisLabelPosition.INSIDE_CHART);
yAxisLeft.setDrawGridLines(false);
yAxisLeft.setDrawAxisLine(false);
yAxisLeft.setEnabled(false);
mChart.getAxisRight().setEnabled(false);
Legend legend = mChart.getLegend();
legend.setEnabled(false);
ArrayList<BarEntry> valueSet1 = new ArrayList<BarEntry>();
for (int i = 0; i < 6; ++i) {
BarEntry entry = new BarEntry(i, (i+1)*10);
valueSet1.add(entry);
}
List<IBarDataSet> dataSets = new ArrayList<>();
BarDataSet barDataSet = new BarDataSet(valueSet1, " ");
barDataSet.setColor(Color.CYAN);
barDataSet.setDrawValues(false);
dataSets.add(barDataSet);
BarData data = new BarData(dataSets);
mChart.setData(data);
mChart.invalidate();
RESULT
I had same issue and resolved by doing this :
barChart.getXAxis().setLabelCount(barDataSet.getEntryCount());
Moreover if you are using only one dataset then instead of this:
ArrayList<IBarDataSet> dataSets = new ArrayList<>();
dataSets.add(barData);
Use:
BarDataSet barDataSet = new BarDataSet(yourValauesHere, "Legend Text here");
For reference please follow example below:
barEntries = new ArrayList<BarEntry>();
barEntries.add(new BarEntry(0, 1));
barEntries.add(new BarEntry(1, 2));
barEntries.add(new BarEntry(2, 4));
barEntries.add(new BarEntry(3, 6));
barEntries.add(new BarEntry(4, 5));
barEntries.add(new BarEntry(5, 7));
barDataSet = new BarDataSet(barEntries, "Contracts");
barDataSet.setAxisDependency(YAxis.AxisDependency.LEFT);
barDataSet.setColor(getColor("defaultYellow"));
barDataSet.setHighlightEnabled(true);
barDataSet.setHighLightColor(Color.RED);
barDataSet.setValueTextSize(defaultValueTextSize);
barDataSet.setValueTextColor(getColor("primaryDark"));
BarData barData = new BarData(barDataSet);
barChart.getDescription().setText("No. of Contracts signed in 6
months");
barChart.getDescription().setTextSize(12);
barChart.getAxisLeft().setAxisMinimum(0);
barChart.getXAxis().setPosition(XAxis.XAxisPosition.BOTH_SIDED);
barChart.getXAxis().setValueFormatter(new
IndexAxisValueFormatter(getXAxisValues()));
barChart.animateY(1000);
barChart.setData(barData);
Getting xAxis values method:
private ArrayList<String> getXAxisValues()
{
ArrayList<String> labels = new ArrayList<String> ();
labels.add( "JAN");
labels.add( "FEB");
labels.add( "MAR");
labels.add( "APR");
labels.add( "MAY");
labels.add( "JUN");
return labels;
}
Handling axis labels like this can be rather complicated sometimes. You have to first make sure the labels are shown at the interval and spacing you want, then you have to use an axis value formatter to transform them to some other string in this case.
The TL;DR is
setCenterAxisLabels does not do what it sounds like it does - don't use it. Labels are already centered under their axis values by default. This centers the labels between axis values.
Use numeric labels to debug label position before applying IndexAxisValueFormatter to make sure you have integer values in the expected locations.
IndexAxisValueFormatter has some buggy rounding logic and doesn't display labels for values between X.5 and X.999999, while values between X.0 and X.499999 get rounded down to X and labels[X] is shown. Use a custom ValueFormatter to fix those issues.
Long Answer
To start with, I used the following test data, which reproduces the behavior you saw (the behavior will be a bit different if your x values start at 0 instead of 1, but the same type of issues will show up). The code here is in Kotlin, but the solution is equally applicable to Java.
val months = listOf("J","F","M","A","M","J","J","A","S","O","N","D")
val yvals = listOf(1f,2f,5f,0.1f,0.5f,1f,0.5f,2f,1f,2.5f,2f,0.2f)
val entries = yvals.mapIndexed { i, y -> BarEntry((i+1).toFloat(),y)}
val barDataSet = BarDataSet(entries,"data")
Initial Approach
When you plot this using your initial chart settings
val xAxis = barChart.xAxis
xAxis.position = XAxis.XAxisPosition.BOTTOM
xAxis.setDrawGridLines(true)
xAxis.setDrawAxisLine(true)
xAxis.setCenterAxisLabels(true)
xAxis.setLabelCount(months.size, true)
xAxis.valueFormatter = IndexAxisValueFormatter(months)
you get the first behavior you saw where half the labels are gone and the rest are not positioned under the bars:
To better understand why this is happening, we can use a different axis value formatter to see where MPAndroidChart is trying to place labels. This will write the numeric values instead of trying to convert them to array indices:
class VerboseAxisValueFormatter : ValueFormatter() {
override fun getFormattedValue(value: Float): String {
return "%.2f".format(value)
}
}
This gives (the values match the ones you saw when debugging)
Looking at the source code for IndexAxisValueFormatter
public String getFormattedValue(float value, AxisBase axis) {
int index = Math.round(value);
if (index < 0 || index >= mValueCount || index != (int)value)
return "";
return mValues[index];
}
the final check in there (index != (int)value) means that if the rounded value is not equal to the truncated (floor) value then the result is blank. This means that for values from 1.0 to 1.499999 it will return mValues[1] but for values from 1.5 to 1.99999 it will return a blank string. That's why the entire first half of the chart was missing labels - the x values it chose to draw axis labels at had decimal portions greater than 0.5.
Second Approach
So for your second iteration, you set the label count to Integer.MAX_VALUE and shifted the values down by 0.5. Doing that here (but leaving the numeric labels on) gives the following, where the labels have nice even spacing (default granularity here is 0.5). If you replaced the integer values here (0.0, 1.0, etc) you would get the result you saw with your "offset label case" (labels were present but not centered)
However, the left bar is centered at 1.0 which is very different from where the label was drawn. This is because xAxis.setCenterAxisLabels(true) does not center labels under their values (which would make sense, but that's actually the default behavior already) but instead centers labels between the actual axis values. Turning this off and removing the 0.5f shift, gives
Now, we finally have integer value labels centered below bars and in the correct positions, which means we can use the IndexAxisValueFormatter - however, the array indices are 0-based and the data set is 1-based. To fix that, you can subtract 1 from the x values either in the data set or in the formatter. Even so, it's not quite right - we get an extra label on the left edge because the -0.5 there rounds and truncates to 0.
Working Solution
In the end, once we have set the label position correctly, the best choice is still to write a custom ValueFormatter that doesn't have all the issues in the built-in IndexAxisValueFormatter. Instead of using index != (int)value we use abs(index - x) > 0.01f so that the behavior is symmetric and only shows labels actually at integer positions.
class FixedIndexAxisValueFormatter(private val offset: Float, private val labels: List<String>) : ValueFormatter()
{
override fun getFormattedValue(value: Float): String {
val x = value - offset
val index = x.roundToInt()
return if( index < 0 || index >= labels.size || abs(index - x) > 0.01f) ""
else labels[index]
}
}
Using this formatter finally gives the correct result
The final settings to get this were
// Force it to draw labels at all positions controlled by the axis
// bounds and granularity
xAxis.setLabelCount(Integer.MAX_VALUE, true)
// These are already the defaults in this case so they're not necessary,
// but good to specify explicitly in case the defaults change later
xAxis.axisMinimum = 0.5f
xAxis.axisMaximum = 12.5f
xAxis.granularity = 0.5f
// Use a better value formatter, with an offset of 1 since the
// data set started at 1
xAxis.valueFormatter = FixedIndexAxisValueFormatter(1f, months)

MPAndroidChart: Barchart xAxis label not centered

I have this grouped bar chart that can set to any number of bars in a group. It will first start with 2 bars in a group. Then if user clicks the button. it will add a new bar in the group. and click again. new bar again. and so on. my goal is to redraw the chart with new bar but the x-axis label must always be in the center of the grouped bar.
I always have a problem on the time when there are 5 bars.
Above, Feb is not centered on the 2nd grouped bar anymore.
Sample code in here:
https://github.com/PhilJay/MPAndroidChart/issues/3505
(I posted the question here too bec it seems that github is not maintained anymore)
In the code, the function resize is core of it that wants to reduce the width of the bars when new bars are added and at the same time increase the scale minima. But to no avail.
Need help
Check this sample grouped bar chart code.
public class MpAndroidGroupedBarChart extends AppCompatActivity {
BarChart mChart;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mChart = (BarChart) findViewById(R.id.bar_chart);
mChart.setDrawBarShadow(false);
mChart.getDescription().setEnabled(false);
mChart.setPinchZoom(false);
mChart.setDrawGridBackground(false);
// empty labels so that the names are spread evenly
String[] labels = {"", "Name1", "Name2", "Name3", "Name4", "Name5", ""};
IAxisValueFormatter xAxisFormatter = new LabelFormatter(mChart, labels);
XAxis xAxis = mChart.getXAxis();
xAxis.setCenterAxisLabels(true);
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
xAxis.setDrawGridLines(false);
xAxis.setGranularity(1f); // only intervals of 1 day
xAxis.setTextColor(Color.BLACK);
xAxis.setTextSize(12);
xAxis.setAxisLineColor(Color.WHITE);
xAxis.setAxisMinimum(1f);
xAxis.setValueFormatter(xAxisFormatter);
YAxis leftAxis = mChart.getAxisLeft();
leftAxis.setTextColor(Color.BLACK);
leftAxis.setTextSize(12);
leftAxis.setAxisLineColor(Color.WHITE);
leftAxis.setDrawGridLines(false);
leftAxis.setGranularity(2);
leftAxis.setLabelCount(8, true);
leftAxis.setPosition(YAxis.YAxisLabelPosition.OUTSIDE_CHART);
mChart.getAxisRight().setEnabled(false);
mChart.getLegend().setEnabled(false);
float[] valOne = {10, 20, 30, 40, 50};
float[] valTwo = {60, 50, 40, 30, 20};
float[] valThree = {20, 10, 30, 60, 40};
float[] valFour = {40, 10, 60, 30, 10};
float[] valFive = {60, 50, 40, 30, 50};
ArrayList<BarEntry> barOne = new ArrayList<>();
ArrayList<BarEntry> barTwo = new ArrayList<>();
ArrayList<BarEntry> barThree = new ArrayList<>();
ArrayList<BarEntry> barFour = new ArrayList<>();
ArrayList<BarEntry> barFive = new ArrayList<>();
for (int i = 0; i < valOne.length; i++) {
barOne.add(new BarEntry(i, valOne[i]));
barTwo.add(new BarEntry(i, valTwo[i]));
barThree.add(new BarEntry(i, valThree[i]));
barFour.add(new BarEntry(i, valFour[i]));
barFive.add(new BarEntry(i, valFive[i]));
}
BarDataSet set1 = new BarDataSet(barOne, "barOne");
set1.setColor(Color.BLUE);
BarDataSet set2 = new BarDataSet(barTwo, "barTwo");
set2.setColor(Color.MAGENTA);
BarDataSet set3 = new BarDataSet(barThree, "barTwo");
set3.setColor(Color.RED);
BarDataSet set4 = new BarDataSet(barFour, "barTwo");
set4.setColor(Color.GREEN);
BarDataSet set5 = new BarDataSet(barFive, "barTwo");
set5.setColor(Color.LTGRAY);
set1.setHighlightEnabled(false);
set1.setDrawValues(false);
set2.setHighlightEnabled(false);
set2.setDrawValues(false);
set3.setHighlightEnabled(false);
set3.setDrawValues(false);
set4.setHighlightEnabled(false);
set4.setDrawValues(false);
set5.setHighlightEnabled(false);
set5.setDrawValues(false);
ArrayList<IBarDataSet> dataSets = new ArrayList<IBarDataSet>();
dataSets.add(set1);
dataSets.add(set2);
dataSets.add(set3);
dataSets.add(set4);
dataSets.add(set5);
BarData data = new BarData(dataSets);
float groupSpace = 0.2f;
float barSpace = 0f;
float barWidth = 0.16f;
// (barSpace + barWidth) * 5 + groupSpace = 1
// multiplied by 5 because there are 5 five bars
// labels will be centered as long as the equation is satisfied
data.setBarWidth(barWidth);
// so that the entire chart is shown when scrolled from right to left
xAxis.setAxisMaximum(labels.length - 1.1f);
mChart.setData(data);
mChart.setScaleEnabled(false);
mChart.setVisibleXRangeMaximum(2f);
mChart.groupBars(1f, groupSpace, barSpace);
mChart.invalidate();
}
private class LabelFormatter implements IAxisValueFormatter {
String[] labels;
BarLineChartBase<?> chart;
LabelFormatter(BarLineChartBase<?> chart, String[] labels) {
this.chart = chart;
this.labels = labels;
}
#Override
public String getFormattedValue(float value, AxisBase axis) {
return labels[(int) value];
}
}
}
labels will be centered as long as this equation is satisfied
(barSpace + barWidth) * 5 + groupSpace = 1
multiplied by 5 because there are 5 five bars
RESULT
first you have to dynamically set the min and max value for x-axis
mChart.getXAxist().setAxisMinimum(0);
mChart.getXAxis().setAxisMaximum(0 +
barChart.getBarData().getGroupWidth(groupSpace, barSpace) * groupCount);
and then set it to center:
mChart.getXAxis().setCenterAxisLabels(true);
I have provided a detailed answer here:
set interval between x-axis labels: stackoverflow
I think the Label position is correct & the problem is with Bar position & Spacing.Please try the following method.
/**
* Group charts by specifying width & other properties externally
*
* #param dataSets Entire DataSet made
* #param data Bar Data created from datasets
* #see http://google.com
*/
private void setupChartGrouping(ArrayList<IBarDataSet> dataSets,
BarData data) {
if (dataSets.size() > 1) {
barChart.getXAxis().setCenterAxisLabels(true);
barChart.getBarData().setBarWidth(getBarWidth(dataSets.size()));
barChart.getXAxis().setAxisMinimum(-data.getBarWidth() / 2);
barChart.getXAxis().setAxisMaximum(dataSets.size());
barChart.groupBars(0, GROUPED_CHART_GROUP_SPACING, GROUPED_CHART_BAR_SPACING);
} else {
barChart.getXAxis().setCenterAxisLabels(false);
barChart.getXAxis().resetAxisMaximum();
barChart.getXAxis().resetAxisMinimum();
barChart.getAxisLeft().setDrawGridLines(false);
barChart.getXAxis().setDrawGridLines(false);
}
}
private static final float GROUPED_CHART_MAGICAL_NUMBER = 1.00f;
public static final float GROUPED_CHART_BAR_SPACING = 0.05f;
public static final float GROUPED_CHART_GROUP_SPACING = 0.20f;
/**
* Size would be ==> ((barSpace + barWidth) * no: of bars in a group) + groupSpace = 1.00
*
* #param barEntryCount No: of bars in a Group
* #return Width of a Single Bar in Chart
*/
public static float getBarWidth(int barEntryCount) {
return ((GROUPED_CHART_MAGICAL_NUMBER - GROUPED_CHART_GROUP_SPACING) / barEntryCount) - GROUPED_CHART_BAR_SPACING;
}
To align x axis at center of groupBarChart you need to fulfill the below formula
Formula :: (barWidth + barSpace)*count + groupSpace = 1 :-count= no of bars/groups
here:
barWdith = ??
barSpace = 0.05f
grouSpace = 0.44f
You can find the barWidth using below formula:
barWidth = (1 - groupSpace) /`enter code here` count - barSpace;

Android: MPAndroidChart first Bar not showing properly

I am using MPAndroidChart for plotting scatteredBarChart. The code is as follows:
Code:
public void setupScatteredBarChart(ArrayList<String> x, ArrayList<String> y1, ArrayList<String> y2 )
{
int maxYvalue = 0;
final String[] x_name = new String[x.size()];
for (int j = 0; j <x.size(); j++)
{
String[] temp = x.get(j).split("-");
x_name[j] = temp[0] + "/" + temp[1];
}
ArrayList<BarEntry> yVals1 = new ArrayList<BarEntry>();
for (int i = 0; i < x_name.length; i++)
{
float val1 = Float.parseFloat(y1.get(i));
float val2 = Float.parseFloat(y2.get(i));
yVals1.add(new BarEntry(i, new float[]{val1, val2},getResources().getDrawable(R.drawable.ic_launcher)));
float val_total = val1 + val2;
int I = (int) Math.ceil(val_total);
if (maxYvalue < I)
{
maxYvalue = I;
}
}
chart_scattered = (BarChart) findViewById(R.id.chart_scattered);
chart_scattered.setOnChartValueSelectedListener(Stat.this);
chart_scattered.getDescription().setEnabled(false);
chart_scattered.setMaxVisibleValueCount(40); // if more than 40 entries are displayed in the chart, no values will be drawn
chart_scattered.setPinchZoom(false); // scaling can now only be done on x- and y-axis separately
chart_scattered.setDrawGridBackground(false);
chart_scattered.setDrawBarShadow(false);
chart_scattered.setDrawValueAboveBar(false);
chart_scattered.setHighlightFullBarEnabled(false);
chart_scattered.setDoubleTapToZoomEnabled(false);
chart_scattered.setTouchEnabled(false);
chart_scattered.setFitBars(true);
chart_scattered.animateXY(800, 800);
chart_scattered.getAxisRight().setEnabled(false);
chart_scattered.getXAxis().setAxisMinimum(-0.5f); // adjust for showing first bar properly
// Left Y axis
YAxis leftAxis = chart_scattered.getAxisLeft(); // change the position of the y-labels
leftAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true)
chart_scattered.getAxisLeft().setLabelCount(maxYvalue + 1, true);
chart_scattered.getAxisLeft().setAxisMinValue(0f);
chart_scattered.getAxisLeft().setValueFormatter(new MyYAxisValueFormatter());
// Bottom X axis
XAxis xLabels = chart_scattered.getXAxis();
xLabels.setPosition(XAxis.XAxisPosition.BOTTOM);
xLabels.setAxisMinimum(0f);
xLabels.setGranularity(1f);
xLabels.setValueFormatter(new IAxisValueFormatter() {
#Override
public String getFormattedValue(float value, AxisBase axis) {
return x_name[(int) value % x_name.length];
}
});
Legend l = chart_scattered.getLegend();
l.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM);
l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT);
l.setOrientation(Legend.LegendOrientation.HORIZONTAL);
l.setDrawInside(false);
l.setFormSize(6f);
l.setFormToTextSpace(4f);
l.setXEntrySpace(6f);
BarDataSet set1;
if (chart_scattered.getData() != null && chart_scattered.getData().getDataSetCount() > 0)
{
set1 = (BarDataSet) chart_scattered.getData().getDataSetByIndex(0);
set1.setValues(yVals1);
chart_scattered.getData().notifyDataChanged();
chart_scattered.notifyDataSetChanged();
}
else
{
set1 = new BarDataSet(yVals1, "");
set1.setDrawIcons(false);
set1.setColors(getColors());
set1.setStackLabels(new String[]{"A", "B"});
ArrayList<IBarDataSet> dataSets = new ArrayList<IBarDataSet>();
dataSets.add(set1);
BarData data = new BarData(dataSets);
data.setValueTextColor(Color.WHITE);
chart_scattered.setData(data);
}
chart_scattered.invalidate();
}
Screen Capture:
Question:
How could the first Bar to be showing properly? I have researched a lot and added the following to the code but is still not successful as showing in the screen capture above.
chart_scattered.getXAxis().setAxisMinimum(-0.5f);
chart_scattered.setFitBars(true);
As the date will go on increasing, could it set max 7 Bars and more than that, it has to be scrolled horizontally?
Thanks!
Question 1
remove this line from your code
xLabels.setAxisMinimum(0f);
will solve your problem.
Question 2
To only show the first 7 bars, use this..
chart_scattered.setVisibleXRangeMaximum(7f);
but this will not allow the user to scroll horizontally yet, if you want to enable scrolling, you'll have to remove this line from your code
chart_scattered.setTouchEnabled(false);
I am assuming you used the above line so the user can't highlight the bars. To keep that behavior, use this function..
chart_scattered.setHighlightPerTapEnabled(false);

MPAndroidChart - CustomValueFormatter renders values out of the Viewport

I've been working with HorizontalBarChart MPAndroidChart a few days ago, and ran into an issue while trying to use a custom ValueFormatter which converts the time from milliseconds into 12h format time. (08:50 AM) But as you can see in the picture below, the value gets clipped...
Is there any possibility to set a padding for the chart on the right for the values to be visible?
Here's the code which configures the chart:
private void initializeChart() {
// Customize user interaction on chart
mHorizontalBarChart.setTouchEnabled(false);
mHorizontalBarChart.setPinchZoom(false);
mHorizontalBarChart.setDragEnabled(false);
// Customize chart's standard settings
mHorizontalBarChart.setDrawGridBackground(false);
mHorizontalBarChart.setDescription("");
mHorizontalBarChart.setHighlightEnabled(false);
mHorizontalBarChart.getLegend().setEnabled(false);
Paint infoPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
infoPaint.setTextAlign(Paint.Align.CENTER);
infoPaint.setTextSize(12f);
mHorizontalBarChart.setPaint(infoPaint, Chart.PAINT_INFO);
// Customize X axis
XAxis xAxis = mHorizontalBarChart.getXAxis();
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
xAxis.setTextSize(12f);
xAxis.setDrawLabels(true);
xAxis.setDrawAxisLine(false);
xAxis.setDrawGridLines(false);
xAxis.setAvoidFirstLastClipping(true);
// Customize Y axis's
// Left
YAxis leftAxis = mHorizontalBarChart.getAxisLeft();
leftAxis.setDrawLabels(false);
leftAxis.setDrawAxisLine(false);
leftAxis.setDrawGridLines(false);
leftAxis.setDrawTopYLabelEntry(false);
// Right
YAxis rightAxis = mHorizontalBarChart.getAxisRight();
rightAxis.setDrawLabels(false);
rightAxis.setDrawAxisLine(false);
rightAxis.setDrawGridLines(false);
rightAxis.setDrawTopYLabelEntry(false);
}
And here's the code which populates it:
private void setChartData(float range) {
String[] daysOfWeek = new String[]{"MO", "TU", "WE", "TH", "FR", "SA", "SU"};
ArrayList<String> xVals = new ArrayList<String>();
for (int i = 0; i < daysOfWeek.length; i++) {
xVals.add(daysOfWeek[i]);
}
ArrayList<BarEntry> yVals1 = new ArrayList<BarEntry>();
for (int i = 0; i < daysOfWeek.length; i++) {
float mult = (range + 1);
float val = (float) (Math.random() * mult);
yVals1.add(new BarEntry(val, i));
}
BarDataSet set1 = new BarDataSet(yVals1, "DataSet");
set1.setBarSpacePercent(35f);
ArrayList<BarDataSet> dataSets = new ArrayList<BarDataSet>();
dataSets.add(set1);
BarData data = new BarData(xVals, dataSets);
data.setValueTextSize(10f);
data.setValueFormatter(new ValueFormatter() {
#Override
public String getFormattedValue(float value) {
return value + "some extra text";
}
});
mHorizontalBarChart.setData(data);
}
Any help is greatly appreciated.
Code is used from the examples provided by #Philipp Jahoda.
EDIT: BASED ON Philipp's answer:
I used setSpaceTop(float percent) to adjust the space for the values of the BarData.
// Customize Y axis's
// Left
YAxis leftAxis = mHorizontalBarChart.getAxisLeft();
leftAxis.setDrawLabels(false);
leftAxis.setDrawAxisLine(false);
leftAxis.setDrawGridLines(false);
leftAxis.setDrawTopYLabelEntry(false);
leftAxis.setSpaceTop(20); // use these to adjust space for the BarData values
// Right
YAxis rightAxis = mHorizontalBarChart.getAxisRight();
rightAxis.setDrawLabels(false);
rightAxis.setDrawAxisLine(false);
rightAxis.setDrawGridLines(false);
rightAxis.setDrawTopYLabelEntry(false);
rightAxis.setSpaceTop(20); // use these to adjust space for the BarData values
Code must be optimized though, this is just a quick test, but these suggestions worth tried out. Thanks again Philipp!
Read the documentation of the YAxis.
Focus on the following methods:
setAxisMaxValue(...) & setAxisMinValue(...)
setSpaceTop(...)
setSpaceBottom(...)
With them you can set the range / space of your axis.

How to set min x, min y, max y, and min y MPAndroidChart to fit chart in chart window

From
https://github.com/PhilJay/MPAndroidChart
I tried fitScreen(), but it had no effect.
How do I set min x, min y, max y, and min y MPAndroidChart to fit chart in chart window ?
Have you already added values to the chart?
If not, call setYRange(...) to set the y-min and y-max. For setting the x-values, simply create a new data object (e.g. LineData) and set your x-values for it:
(this example will create x-min: 0 and x-max: 30)
private void addEmptyData() {
// create 30 x-vals
String[] xVals = new String[30];
for (int i = 0; i < 30; i++)
xVals[i] = "" + i;
// create a chartdata object that contains only the x-axis labels (no entries or datasets)
LineData data = new LineData(xVals);
mChart.setData(data);
mChart.invalidate();
}
This will create an empty chart with your desired bounds.
For dynamically adding entries, refer this: https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java

Categories

Resources