I am working on a groupped Barchart using mpandroidchart library:
Code:
public void drawing_length(String length)
{
ArrayList<String> xx = new ArrayList<String>();
ArrayList<String> yy = new ArrayList<String>();
ArrayList<String> zz = new ArrayList<String>();
int L = 7;
if (length.equals("7days"))
{
L = 7;
}
if (length.equals("14days"))
{
L = 14;
}
if (length.equals("30days"))
{
L = 30;
}
if (L > x.size())
{
L = x.size();
}
for (int g=0; g<L; g++)
{
xx.add(x.get(g)); // newest first, oldest last
yy.add(y.get(g));
zz.add(z.get(g));
}
Collections.reverse(xx); //oldest first, newest last, i.e. sequential
Collections.reverse(yy);
Collections.reverse(zz);
setupGrouppedChart(xx,yy,zz);
}
public void setupGrouppedChart(ArrayList<String> x, ArrayList<String> y1, ArrayList<String> y2)
{
float barWidth;
float barSpace;
float groupSpace;
barWidth = 0.3f;
barSpace = 0f;
groupSpace = 0.4f;
ll_combined_chart.setVisibility(View.GONE);
ll_scatteredchart.setVisibility(View.GONE);
ll_groupped_barchart.setVisibility(View.VISIBLE);
chart_grouppedBar = (BarChart) findViewById(R.id.chart_grouppedBar);
chart_grouppedBar.getDescription().setEnabled(false);
chart_grouppedBar.setBackgroundColor(Color.TRANSPARENT);
chart_grouppedBar.setDrawGridBackground(false);
chart_grouppedBar.setPinchZoom(false);
chart_grouppedBar.setScaleEnabled(false);
chart_grouppedBar.setDrawBarShadow(false);
chart_grouppedBar.setDrawValueAboveBar(false);
chart_grouppedBar.setHighlightFullBarEnabled(false);
chart_grouppedBar.setHighlightPerDragEnabled(false);
chart_grouppedBar.setHighlightPerTapEnabled(false);
chart_grouppedBar.setDoubleTapToZoomEnabled(false);
chart_grouppedBar.getXAxis().setDrawGridLines(false);
chart_grouppedBar.getAxisLeft().setDrawGridLines(false);
chart_grouppedBar.getAxisRight().setDrawGridLines(false);
chart_grouppedBar.getAxisRight().setEnabled(false);
chart_grouppedBar.animateXY(800, 800);
chart_grouppedBar.getDescription().setText("This is testing Description");
chart_grouppedBar.setVisibleXRangeMaximum(14f);
Utilities.custom_toast(Stat.this, "Xsize=" + x.size(), "gone", "short");
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];
}
XAxis xLabels = chart_grouppedBar.getXAxis();
xLabels.setPosition(XAxis.XAxisPosition.BOTTOM);
xLabels.setGranularity(1f);
xLabels.setValueFormatter(new IAxisValueFormatter()
{
#Override
public String getFormattedValue(float value, AxisBase axis)
{
return x_name[(int) value % x_name.length];
}
});
BarDataSet set1, set2;
ArrayList<BarEntry> valueSet1 = new ArrayList<>();
ArrayList<BarEntry> valueSet2 = new ArrayList<>();
for (int i = 0; i < x_name.length; i++)
{
float val1 = Float.parseFloat(y1.get(i));
BarEntry v1e1 = new BarEntry(i, val1);
valueSet1.add(v1e1);
float val2 = Float.parseFloat(y2.get(i));
BarEntry v1e2 = new BarEntry(i, val2);
valueSet2.add(v1e2);
}
if (chart_grouppedBar.getData() != null && chart_grouppedBar.getData().getDataSetCount() > 0)
{
set1 = (BarDataSet) chart_grouppedBar.getData().getDataSetByIndex(0);
set2 = (BarDataSet) chart_grouppedBar.getData().getDataSetByIndex(1);
set1.setValues(valueSet1);
set2.setValues(valueSet2);
chart_grouppedBar.getData().setHighlightEnabled(false);
chart_grouppedBar.groupBars(0, groupSpace, barSpace);
chart_grouppedBar.getData().notifyDataChanged();
chart_grouppedBar.notifyDataSetChanged();
}
else
{
set1 = new BarDataSet(valueSet1, "A");
set1.setColor(getResources().getColor(R.color.pink_light));
set2 = new BarDataSet(valueSet2, "B");
set2.setColor(getResources().getColor(R.color.purple1));
BarData data = new BarData(set1, set2);
//data.setValueFormatter(new LargeValueFormatter());
//data.setValueTypeface(mTfLight);
data.setValueFormatter(new MyValueFormatter());
chart_grouppedBar.setData(data);
chart_grouppedBar.getBarData().setBarWidth(barWidth);
chart_grouppedBar.getXAxis().setAxisMaximum(0 + chart_grouppedBar.getBarData().getGroupWidth(groupSpace, barSpace) * x_name.length);
chart_grouppedBar.getAxisLeft().setAxisMinimum(0);
chart_grouppedBar.getAxisLeft().setValueFormatter(new MyYAxisValueFormatter());
chart_grouppedBar.getData().setHighlightEnabled(false);
chart_grouppedBar.groupBars(0, groupSpace, barSpace);
chart_grouppedBar.invalidate(); // refresh
}
}
Screen capture:
Question:
The legend for the x-axis is shifted. How can it be adjusted?
There should be 9 entries but it is now only showing 7 entries. I suspect it is on the right but the screen cannot be scrolled to the right. The toast report the size is 9 correctly. How could the chart be scrollable?
The Y-axis is also wrong. The height of the bars do not match with the Y-axis.
Thank you.
Hard-Coded bar width is the problem.Find bar width dynamically like below
((1.00f- 0.20f) / barEntryCount) - 0.05f
where
0.05f -> Bar Spacing;
0.20f -> Group Spacing;
Please read this thread.
Regarding alignment of X Axis Labels (Question 1)
do like following
if (dataSets.size() > 1) {
barChart.getXAxis().setCenterAxisLabels(true);
else
barChart.getXAxis().setCenterAxisLabels(false);
Regarding the 2nd question
Please verify that your dataset count is 9.If you given 9 elements in dataset surly ,it will plot.Please check other view properties including view clipping.
For your 2nd question
How could the chart be scrollable?
chart_grouppedBar.setDragEnabled(true);
Reference link
For 3rd question
The Y-axis is also wrong. The height of the bars do not match with the
Y-axis.
try to set Min & Max value of axis and label count. For example:
chart_grouppedBar.getAxisLeft().setAxisMaxValue(MAX VALUE FROM YOUR DATASET);
chart_grouppedBar.getAxisLeft().setLabelCount(8, true);
reference link
Related
I want to plot Bar charts in an Android app similar to "Health" app of iOS.
Here are screenshots.
I tried to plot using MPAndroidChart.
I have seen examples given in that library but didn't able to plot as per my requirement.
I am able to display bars for 1 year graph (2nd screenshot) because it has 12 data points and 12 x-axis labels.
But for one day graph, there is a need to display bars between 2 labels of x-axis.
Also didn't understand how I map the time duration of 24 hours or any other on x-axis and its value.
Is there any way from which I can make X-axis as a time or date axis according to selected tabs ?
X-axis labels will be dynamic as per the current date and time. So I cannot set a fixed String array and also need to map values and x-axis timings.
Can anyone please help to map data and time axis?
You can draw the day times in the same way you render the months but instead of 12 values you will have 24 (one value for each time). The only difference is that the times graph has only 4 X-labels instead of 12 for months and it renders the times: 12AM, 6AM, 12PM, 6PM only and all the other time labels have empty values.
Below i will describe how you can plot and map each Y-Value with its corresponding X-Label with code examples:
1.Add the BarChart into an Activity xml layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.github.mikephil.charting.charts.BarChart
android:id="#+id/barChart"
android:layout_width="match_parent"
android:layout_height="300dp" />
</RelativeLayout>
2.Get a reference to the BarChart
mBarChart = findViewById(R.id.barChart);
3.Plot the Months Chart using the below function:
private void showMonthsBars(){
//input Y data (Months Data - 12 Values)
ArrayList<Double> valuesList = new ArrayList<Double>();
valuesList.add((double)1800);
valuesList.add((double)1600);
valuesList.add((double)500);
valuesList.add((double)1500);
valuesList.add((double)900);
valuesList.add((double)1700);
valuesList.add((double)400);
valuesList.add((double)2000);
valuesList.add((double)2500);
valuesList.add((double)3500);
valuesList.add((double)3000);
valuesList.add((double)1800);
//prepare Bar Entries
ArrayList<BarEntry> entries = new ArrayList<>();
for (int i = 0; i < valuesList.size(); i++) {
BarEntry barEntry = new BarEntry(i+1, valuesList.get(i).floatValue()); //start always from x=1 for the first bar
entries.add(barEntry);
}
//initialize x Axis Labels (labels for 13 vertical grid lines)
final ArrayList<String> xAxisLabel = new ArrayList<>();
xAxisLabel.add("J"); //this label will be mapped to the 1st index of the valuesList
xAxisLabel.add("F");
xAxisLabel.add("M");
xAxisLabel.add("A");
xAxisLabel.add("M");
xAxisLabel.add("J");
xAxisLabel.add("J");
xAxisLabel.add("A");
xAxisLabel.add("S");
xAxisLabel.add("O");
xAxisLabel.add("N");
xAxisLabel.add("D");
xAxisLabel.add(""); //empty label for the last vertical grid line on Y-Right Axis
//initialize xAxis
XAxis xAxis = mBarChart.getXAxis();
xAxis.enableGridDashedLine(10f, 10f, 0f);
xAxis.setTextColor(Color.BLACK);
xAxis.setTextSize(14);
xAxis.setDrawAxisLine(true);
xAxis.setAxisLineColor(Color.BLACK);
xAxis.setDrawGridLines(true);
xAxis.setGranularity(1f);
xAxis.setGranularityEnabled(true);
xAxis.setAxisMinimum(0 + 0.5f); //to center the bars inside the vertical grid lines we need + 0.5 step
xAxis.setAxisMaximum(entries.size() + 0.5f); //to center the bars inside the vertical grid lines we need + 0.5 step
xAxis.setLabelCount(xAxisLabel.size(), true); //draw x labels for 13 vertical grid lines
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
xAxis.setXOffset(0f); //labels x offset in dps
xAxis.setYOffset(0f); //labels y offset in dps
xAxis.setCenterAxisLabels(true);
xAxis.setValueFormatter(new ValueFormatter() {
#Override
public String getFormattedValue(float value) {
return xAxisLabel.get((int) value);
}
});
//initialize Y-Right-Axis
YAxis rightAxis = mBarChart.getAxisRight();
rightAxis.setTextColor(Color.BLACK);
rightAxis.setTextSize(14);
rightAxis.setDrawAxisLine(true);
rightAxis.setAxisLineColor(Color.BLACK);
rightAxis.setDrawGridLines(true);
rightAxis.setGranularity(1f);
rightAxis.setGranularityEnabled(true);
rightAxis.setAxisMinimum(0);
rightAxis.setAxisMaximum(6000f);
rightAxis.setLabelCount(4, true); //draw y labels (Y-Values) for 4 horizontal grid lines starting from 0 to 6000f (step=2000)
rightAxis.setPosition(YAxis.YAxisLabelPosition.OUTSIDE_CHART);
//initialize Y-Left-Axis
YAxis leftAxis = mBarChart.getAxisLeft();
leftAxis.setAxisMinimum(0);
leftAxis.setDrawAxisLine(true);
leftAxis.setLabelCount(0, true);
leftAxis.setValueFormatter(new ValueFormatter() {
#Override
public String getFormattedValue(float value) {
return "";
}
});
//set the BarDataSet
BarDataSet barDataSet = new BarDataSet(entries, "Months");
barDataSet.setColor(Color.RED);
barDataSet.setFormSize(15f);
barDataSet.setDrawValues(false);
barDataSet.setValueTextSize(12f);
//set the BarData to chart
BarData data = new BarData(barDataSet);
mBarChart.setData(data);
mBarChart.setScaleEnabled(false);
mBarChart.getLegend().setEnabled(false);
mBarChart.setDrawBarShadow(false);
mBarChart.getDescription().setEnabled(false);
mBarChart.setPinchZoom(false);
mBarChart.setDrawGridBackground(true);
mBarChart.invalidate();
}
or plot the 24-Hours of a day like the below:
private void showDayHoursBars(){
//input Y data (Day Hours - 24 Values)
ArrayList<Double> valuesList = new ArrayList<Double>();
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)100);
valuesList.add((double)270);
valuesList.add((double)430);
valuesList.add((double)110);
valuesList.add((double)30);
valuesList.add((double)200);
valuesList.add((double)180);
valuesList.add((double)0);
valuesList.add((double)140);
valuesList.add((double)160);
valuesList.add((double)0);
valuesList.add((double)100);
valuesList.add((double)0);
valuesList.add((double)750);
valuesList.add((double)1200);
valuesList.add((double)10);
valuesList.add((double)0);
//initialize x Axis Labels (labels for 25 vertical grid lines)
final ArrayList<String> xAxisLabel = new ArrayList<>();
for(int i = 0; i < 24; i++){
switch (i){
case 0:
xAxisLabel.add("12 AM"); //12AM - 5AM
break;
case 6:
xAxisLabel.add("6"); //6AM - 11AM
break;
case 12:
xAxisLabel.add("12 PM"); //12PM - 5PM
break;
case 18:
xAxisLabel.add("6"); //6PM - 11PM
break;
default:
xAxisLabel.add(String.format(Locale.US, "%02d", i)+":00");
break;
}
}
xAxisLabel.add(""); //empty label for the last vertical grid line on Y-Right Axis
//prepare Bar Entries
ArrayList<BarEntry> entries = new ArrayList<>();
for (int i = 0; i < valuesList.size(); i++) {
BarEntry barEntry = new BarEntry(i+1, valuesList.get(i).floatValue()); //start always from x=1 for the first bar
entries.add(barEntry);
}
//initialize xAxis
XAxis xAxis = mBarChart.getXAxis();
xAxis.enableGridDashedLine(10f, 10f, 0f);
xAxis.setTextColor(Color.BLACK);
xAxis.setTextSize(14);
xAxis.setDrawAxisLine(true);
xAxis.setAxisLineColor(Color.BLACK);
xAxis.setDrawGridLines(true);
xAxis.setGranularity(1f);
xAxis.setGranularityEnabled(true);
xAxis.setAxisMinimum(0 + 0.5f); //to center the bars inside the vertical grid lines we need + 0.5 step
xAxis.setAxisMaximum(entries.size() + 0.5f); //to center the bars inside the vertical grid lines we need + 0.5 step
xAxis.setLabelCount(5, true); //show only 5 labels (5 vertical grid lines)
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
xAxis.setXOffset(0f); //labels x offset in dps
xAxis.setYOffset(0f); //labels y offset in dps
//xAxis.setCenterAxisLabels(true); //don't center the x labels as we are using a custom XAxisRenderer to set the label x, y position
xAxis.setValueFormatter(new ValueFormatter() {
#Override
public String getFormattedValue(float value) {
return xAxisLabel.get((int) value);
}
});
//initialize Y-Right-Axis
YAxis rightAxis = mBarChart.getAxisRight();
rightAxis.setTextColor(Color.BLACK);
rightAxis.setTextSize(14);
rightAxis.setDrawAxisLine(true);
rightAxis.setAxisLineColor(Color.BLACK);
rightAxis.setDrawGridLines(true);
rightAxis.setGranularity(1f);
rightAxis.setGranularityEnabled(true);
rightAxis.setAxisMinimum(0);
rightAxis.setAxisMaximum(1500f);
rightAxis.setLabelCount(4, true); //labels (Y-Values) for 4 horizontal grid lines
rightAxis.setPosition(YAxis.YAxisLabelPosition.OUTSIDE_CHART);
//initialize Y-Left-Axis
YAxis leftAxis = mBarChart.getAxisLeft();
leftAxis.setAxisMinimum(0);
leftAxis.setDrawAxisLine(true);
leftAxis.setLabelCount(0, true);
leftAxis.setValueFormatter(new ValueFormatter() {
#Override
public String getFormattedValue(float value) {
return "";
}
});
//set the BarDataSet
BarDataSet barDataSet = new BarDataSet(entries, "Hours");
barDataSet.setColor(Color.RED);
barDataSet.setFormSize(15f);
barDataSet.setDrawValues(false);
barDataSet.setValueTextSize(12f);
//set the BarData to chart
BarData data = new BarData(barDataSet);
mBarChart.setData(data);
mBarChart.setScaleEnabled(false);
mBarChart.getLegend().setEnabled(false);
mBarChart.setDrawBarShadow(false);
mBarChart.getDescription().setEnabled(false);
mBarChart.setPinchZoom(false);
mBarChart.setDrawGridBackground(true);
mBarChart.setXAxisRenderer(new XAxisRenderer(mBarChart.getViewPortHandler(), mBarChart.getXAxis(), mBarChart.getTransformer(YAxis.AxisDependency.LEFT)){
#Override
protected void drawLabel(Canvas c, String formattedLabel, float x, float y, MPPointF anchor, float angleDegrees) {
//for 6AM and 6PM set the correct label x position based on your needs
if(!TextUtils.isEmpty(formattedLabel) && formattedLabel.equals("6"))
Utils.drawXAxisValue(c, formattedLabel, x+Utils.convertDpToPixel(5f), y+Utils.convertDpToPixel(1f), mAxisLabelPaint, anchor, angleDegrees);
//for 12AM and 12PM set the correct label x position based on your needs
else
Utils.drawXAxisValue(c, formattedLabel, x+Utils.convertDpToPixel(20f), y+Utils.convertDpToPixel(1f), mAxisLabelPaint, anchor, angleDegrees);
}
});
mBarChart.invalidate();
}
From the above examples i have used some dummy data to show the mapping between Y-Values and X-Values. One main difference between Month-Chart and Day-Chart is that in Month-Chart i have centered the x-labels inside each Bar using the xAxis.setCenterAxisLabels(true); and in Day-Chart i have used a custom XAxisRenderer to align each label to the correct x,y position based on your screenshot.
Below are the results for the above codes:
Months-BarChart:
DayHours-BarChart:
Note: This was tested with com.github.PhilJay:MPAndroidChart:v3.1.0.
Example to map X-Axis Timestamps with Y-Values:
In case you already have the Timestamps for X-Axis you can convert them to the appropriate String Label value which will be mapped to the corresponding index of Y-Data values.
Below is an example of how you can plot the Times-Graph starting from the timestamp eg: 27-02-2022 16:00. Here i am converting the Timestamp to a Calendar object using the cal.setTimeInMillis() and then i am using this Calendar to get the new hour in the loop using the cal.add(Calendar.HOUR_OF_DAY, 1); which is used as the Time label in X-Axis like String dayHour = DateFormat.format("hh a", cal).toString().toUpperCase(); in the format you wish to be dispayed in X-Axis. Each Y-Data value corresponds to the appropriate index of X-Axis. The below example starts from 4 PM until 3 PM to handle the 24 hours of a day:
//input Y data (Day Hours - 24 Values)
ArrayList<Double> valuesList = new ArrayList<Double>();
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)100);
valuesList.add((double)270);
valuesList.add((double)430);
valuesList.add((double)110);
valuesList.add((double)30);
valuesList.add((double)200);
valuesList.add((double)180);
valuesList.add((double)0);
valuesList.add((double)140);
valuesList.add((double)160);
valuesList.add((double)0);
valuesList.add((double)100);
valuesList.add((double)0);
valuesList.add((double)750);
valuesList.add((double)1200);
valuesList.add((double)10);
valuesList.add((double)0);
//in case you already have the timestamp for a day then do the following:
//convert the timestamp to calendar by using the cal.setTimeInMillis() and then use the Calendar to iterate the 24H using the cal.add(Calendar.HOUR_OF_DAY, 1);
//like the below example:
//get a dummy TimeStamp for 27-02-2022 16:00
Date date = new Date();
long dateTimeStamp = 0;
try {
String strDate = "27-02-2022 16:00";
date = new SimpleDateFormat("dd-MM-yyyy HH:mm", Locale.US).parse(strDate);
if(date!=null) {
dateTimeStamp = date.getTime();
}
}catch (Exception e){}
//convert the above timestamp to Calendar using the cal.setTimeInMillis()
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(dateTimeStamp);
//this is the day from the above Calendar
String day = DateFormat.format("dd-MM-yyyy HH:mm", cal).toString(); //this is: 27-02-2022 16:00
//initialize x Axis Labels (labels for 25 vertical grid lines)
final ArrayList<String> xAxisLabel = new ArrayList<>();
//iterate all 24 hours to add the label for each time
for(int i = 0; i < 24; i++){
//get current hour in format "hh a" which is eg: 12 AM, 01 AM, etc..
String dayHour = DateFormat.format("hh a", cal).toString().toUpperCase();
//get the hour 0-11 AM or 0-11 PM
int hour = cal.get(Calendar.HOUR);
//check if the above hour is AM or PM (0=AM, 1=PM)
int amPm = cal.get(Calendar.AM_PM);
//this is the current TimeStamp for the current working hour in the loop:
long timeStamp = cal.getTimeInMillis();
//add the dayHour String as the label you want to display in xAxis
xAxisLabel.add(dayHour); //this will be mapped to the corresponding index of the valuesList (Y-Data List)
//increment the Calendar.HOUR_OF_DAY plus +1 to go to the next hour in 24H format
cal.add(Calendar.HOUR_OF_DAY, 1);
}
xAxisLabel.add(""); //empty label for the last vertical grid line on Y-Right Axis
Here is the full code:
private void showDayHoursBars() {
//input Y data (Day Hours - 24 Values)
ArrayList<Double> valuesList = new ArrayList<Double>();
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)100);
valuesList.add((double)270);
valuesList.add((double)430);
valuesList.add((double)110);
valuesList.add((double)30);
valuesList.add((double)200);
valuesList.add((double)180);
valuesList.add((double)0);
valuesList.add((double)140);
valuesList.add((double)160);
valuesList.add((double)0);
valuesList.add((double)100);
valuesList.add((double)0);
valuesList.add((double)750);
valuesList.add((double)1200);
valuesList.add((double)10);
valuesList.add((double)0);
//in case you already have the timestamp for a day then do the following:
//convert the timestamp to calendar by using the cal.setTimeInMillis() and then use the Calendar to iterate the 24H using the cal.add(Calendar.HOUR_OF_DAY, 1);
//like the below example:
//get a dummy TimeStamp for 27-02-2022 16:00
Date date = new Date();
long dateTimeStamp = 0;
try {
String strDate = "27-02-2022 16:00";
date = new SimpleDateFormat("dd-MM-yyyy HH:mm", Locale.US).parse(strDate);
if(date!=null) {
dateTimeStamp = date.getTime();
}
}catch (Exception e){}
//convert the above timestamp to Calendar using the cal.setTimeInMillis()
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(dateTimeStamp);
//this is the day from the above Calendar
String day = DateFormat.format("dd-MM-yyyy HH:mm", cal).toString(); //this is: 27-02-2022 16:00
//initialize x Axis Labels (labels for 25 vertical grid lines)
final ArrayList<String> xAxisLabel = new ArrayList<>();
//iterate all 24 hours to add the label for each time
for(int i = 0; i < 24; i++){
//get current hour in format "hh a" which is eg: 12 AM, 01 AM, etc..
String dayHour = DateFormat.format("hh a", cal).toString().toUpperCase();
//get the hour 0-11 AM or 0-11 PM
int hour = cal.get(Calendar.HOUR);
//check if the above hour is AM or PM (0=AM, 1=PM)
int amPm = cal.get(Calendar.AM_PM);
//this is the current TimeStamp for the current working hour in the loop:
long timeStamp = cal.getTimeInMillis();
//add the dayHour String as the label you want to display in xAxis
xAxisLabel.add(dayHour); //this will be mapped to the corresponding index of the valuesList (Y-Data List)
//increment the Calendar.HOUR_OF_DAY plus +1 to go to the next hour in 24H format
cal.add(Calendar.HOUR_OF_DAY, 1);
}
xAxisLabel.add(""); //empty label for the last vertical grid line on Y-Right Axis
//prepare Bar Entries
ArrayList<BarEntry> entries = new ArrayList<>();
for (int i = 0; i < valuesList.size(); i++) {
BarEntry barEntry = new BarEntry(i+1, valuesList.get(i).floatValue()); //start always from x=1 for the first bar
entries.add(barEntry);
}
//initialize xAxis
XAxis xAxis = mBarChart.getXAxis();
xAxis.enableGridDashedLine(10f, 10f, 0f);
xAxis.setTextColor(Color.BLACK);
xAxis.setTextSize(14);
xAxis.setDrawAxisLine(true);
xAxis.setAxisLineColor(Color.BLACK);
xAxis.setDrawGridLines(true);
xAxis.setGranularity(1f);
xAxis.setGranularityEnabled(true);
xAxis.setAxisMinimum(0 + 0.5f); //to center the bars inside the vertical grid lines we need + 0.5 step
xAxis.setAxisMaximum(entries.size() + 0.5f); //to center the bars inside the vertical grid lines we need + 0.5 step
xAxis.setLabelCount(5, true); //show only 5 labels (5 vertical grid lines)
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
xAxis.setXOffset(0f); //labels x offset in dps
xAxis.setYOffset(0f); //labels y offset in dps
//xAxis.setCenterAxisLabels(true); //don't center the x labels as we are using a custom XAxisRenderer to set the label x, y position
xAxis.setValueFormatter(new ValueFormatter() {
#Override
public String getFormattedValue(float value) {
return xAxisLabel.get((int) value);
}
});
//initialize Y-Right-Axis
YAxis rightAxis = mBarChart.getAxisRight();
rightAxis.setTextColor(Color.BLACK);
rightAxis.setTextSize(14);
rightAxis.setDrawAxisLine(true);
rightAxis.setAxisLineColor(Color.BLACK);
rightAxis.setDrawGridLines(true);
rightAxis.setGranularity(1f);
rightAxis.setGranularityEnabled(true);
rightAxis.setAxisMinimum(0);
rightAxis.setAxisMaximum(1500f);
rightAxis.setLabelCount(4, true); //labels (Y-Values) for 4 horizontal grid lines
rightAxis.setPosition(YAxis.YAxisLabelPosition.OUTSIDE_CHART);
//initialize Y-Left-Axis
YAxis leftAxis = mBarChart.getAxisLeft();
leftAxis.setAxisMinimum(0);
leftAxis.setDrawAxisLine(true);
leftAxis.setLabelCount(0, true);
leftAxis.setValueFormatter(new ValueFormatter() {
#Override
public String getFormattedValue(float value) {
return "";
}
});
//set the BarDataSet
BarDataSet barDataSet = new BarDataSet(entries, "Hours");
barDataSet.setColor(Color.RED);
barDataSet.setFormSize(15f);
barDataSet.setDrawValues(false);
barDataSet.setValueTextSize(12f);
//set the BarData to chart
BarData data = new BarData(barDataSet);
mBarChart.setData(data);
mBarChart.setScaleEnabled(false);
mBarChart.getLegend().setEnabled(false);
mBarChart.setDrawBarShadow(false);
mBarChart.getDescription().setEnabled(false);
mBarChart.setPinchZoom(false);
mBarChart.setDrawGridBackground(true);
mBarChart.setXAxisRenderer(new XAxisRenderer(mBarChart.getViewPortHandler(), mBarChart.getXAxis(), mBarChart.getTransformer(YAxis.AxisDependency.LEFT)){
#Override
protected void drawLabel(Canvas c, String formattedLabel, float x, float y, MPPointF anchor, float angleDegrees) {
//for 6AM and 6PM set the correct label x position based on your needs
if(!TextUtils.isEmpty(formattedLabel) && formattedLabel.equals("6"))
Utils.drawXAxisValue(c, formattedLabel, x+Utils.convertDpToPixel(5f), y+Utils.convertDpToPixel(1f), mAxisLabelPaint, anchor, angleDegrees);
//for 12AM and 12PM set the correct label x position based on your needs
else
Utils.drawXAxisValue(c, formattedLabel, x+Utils.convertDpToPixel(20f), y+Utils.convertDpToPixel(1f), mAxisLabelPaint, anchor, angleDegrees);
}
});
mBarChart.invalidate();
}
And here is the new Result (4 PM until 3 PM):
Example 2 to map X-Axis Timestamps with Y-Values:
Below is another example of how you can map the X(timestamps) with Y(Values):
//prepare X,Y data
ArrayList<Double> valuesList = new ArrayList<Double>();
ArrayList<Long> xAxisLabel = new ArrayList<>();
for(int i = 0; i < 24; i++){
valuesList.add((double)100+i); //y-values
xAxisLabel.add(1645970400000L+i); //x-timestamps
}
xAxisLabel.add(0L); //empty x for the last vertical grid line on Y-Right Axis
//prepare Bar Entries
ArrayList<BarEntry> entries = new ArrayList<>();
for (int i = 0; i < valuesList.size(); i++) {
BarEntry barEntry = new BarEntry(i+1, valuesList.get(i).floatValue()); //start always from x=1 for the first bar
entries.add(barEntry);
}
And based on the above mapping you can use the setLabelCount to render how many labels you wish on X-Axis. Eg: using xAxis.setLabelCount(xAxisLabel.size(), true); you can render all the labels in X-axis.
The callback getFormattedValue(float value) is called every time a specific X-index is ready to be rendered on the graph so you have to get the index first and from that you can get the correct timestamp from the list like in the below example:
//initialize xAxis
XAxis xAxis = mBarChart.getXAxis();
xAxis.setLabelCount(xAxisLabel.size(), true); //show all the labels
xAxis.setValueFormatter(new ValueFormatter() {
#Override
public String getFormattedValue(float value) {
int xIndex = (int) value;
if(xIndex == xAxisLabel.size()-1)
return "";
Long timeStamp = xAxisLabel.get(xIndex);
//here convert the timestamp to the appropriate String value
return String.valueOf(timeStamp);
}
});
And below is the X-Timestamps Result for all labels based on the above sample. To render the labels like in the below picture i have made also the below changes:
xAxis.setLabelRotationAngle(90); //this rotates the x labels to 90 degrees
mBarChart.setXAxisRenderer(new XAxisRenderer(mBarChart.getViewPortHandler(), mBarChart.getXAxis(), mBarChart.getTransformer(YAxis.AxisDependency.LEFT)){
#Override
protected void drawLabel(Canvas c, String formattedLabel, float x, float y, MPPointF anchor, float angleDegrees) {
Utils.drawXAxisValue(c, formattedLabel, x+Utils.convertDpToPixel(5f), y, mAxisLabelPaint, anchor, angleDegrees);
}
});
Timestamps Result:
X-Timestamps for every 10 seconds with a horizontal scroll. Each page has 10 timestamps.
Below i will show the key points of how you can modify the above code to handle the X-Y mapping to show X-Timestamps for every 10 seconds:
int visibleXValuesPerPage = 10;
//get a dummy TimeStamp for 27-02-2022 16:00
Date date = new Date();
long dateTimeStamp = 0;
try {
String strDate = "27-02-2022 16:00";
date = new SimpleDateFormat("dd-MM-yyyy HH:mm", Locale.US).parse(strDate);
if(date!=null) {
dateTimeStamp = date.getTime();
}
}catch (Exception e){}
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(dateTimeStamp);
ArrayList<Double> valuesList = new ArrayList<Double>();
ArrayList<Long> xAxisLabel = new ArrayList<>();
//1h = 3600 seconds
//1d = 86400 seconds
//1w = 604800 seconds
int seconds = 3600;
//the loop here is incremented by 10 seconds (i+=10)
for(int i = 0; i < seconds; i+=10){
String time = DateFormat.format("dd-MM-yyyy HH:mm:ss", cal).toString();
long timeStamp = cal.getTimeInMillis();
valuesList.add((double)i);
xAxisLabel.add(timeStamp);
cal.add(Calendar.SECOND, 10);
}
ArrayList<BarEntry> entries = new ArrayList<>();
for (int i = 0; i < valuesList.size(); i++) {
BarEntry barEntry = new BarEntry(i+1, valuesList.get(i).floatValue());
entries.add(barEntry);
}
XAxis xAxis = mBarChart.getXAxis();
xAxis.setAxisMinimum(0 + 0.5f);
xAxis.setAxisMaximum(entries.size() + 0.5f);
xAxis.setLabelCount(visibleXValuesPerPage, false);
xAxis.setLabelRotationAngle(90);
xAxis.setCenterAxisLabels(true);
xAxis.setValueFormatter(new ValueFormatter() {
#Override
public String getFormattedValue(float value) {
if (value >= 0)
{
int xIndex = (int)value;
if (value > xAxisLabel.size()-1 && value <= xAxisLabel.size())
return "";
if (xIndex < xAxisLabel.size())
{
Long timeStamp = xAxisLabel.get(xIndex);
//here convert the timestamp to the appropriate String value
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(timeStamp);
String time = DateFormat.format("dd-MM-yyyy HH:mm:ss", cal).toString();
return String.valueOf(time);
}
return "";
}
return "";
}
});
//set the BarData to chart
mBarChart.setVisibleXRangeMaximum(visibleXValuesPerPage);
mBarChart.invalidate();
I m using MPAndroidChart Combined Chart to display a Bar & Scatter chart. On click on points of Scatter Graph i m showing a custom marker which is as below :
public class YourMarkerView extends MarkerView {
private TextView tvContent;
private RelativeLayout mainbackground;
/**
* Constructor. Sets up the MarkerView with a custom layout resource.
*
* #param context
* #param layoutResource the layout resource to use for the MarkerView
*/
public YourMarkerView(Context context, int layoutResource) {
super(context, layoutResource);
tvContent = (TextView) findViewById(R.id.tvContent);
mainbackground = (RelativeLayout) findViewById(R.id.mainbackground);
}
// callbacks everytime the MarkerView is redrawn, can be used to update the
// content (user-interface)
#Override
public void refreshContent(Entry e, Highlight highlight) {
if(e!=null && e.getData()!=null){
Log.d("Yoyo",e.getData().toString());
mainbackground.setBackgroundColor(Color.parseColor(e.getData().toString().split(";")[1]));
tvContent.setText("" + e.getData().toString().split(";")[0]);
// this will perform necessary layouting
super.refreshContent(e, highlight);
}
}
private MPPointF mOffset;
#Override
public MPPointF getOffset() {
if(mOffset == null) {
// center the marker horizontally and vertically
mOffset = new MPPointF(-(getWidth() / 2), -getHeight());
}
return mOffset;
}
}
Below is code for Chart:
chart.getDescription().setEnabled(false);
chart.setBackgroundColor(Color.parseColor("#f9f9f9"));
chart.setDrawGridBackground(false);
chart.setDrawBarShadow(false);
chart.setHighlightFullBarEnabled(false);
// draw bars behind lines
chart.setDrawOrder(new CombinedChart.DrawOrder[]{
CombinedChart.DrawOrder.BAR, CombinedChart.DrawOrder.SCATTER
});
chart.getAxisRight().setEnabled(false);
chart.getAxisLeft().setEnabled(false);
chart.getXAxis().setEnabled(false);
Legend legend = chart.getLegend();
legend.setEnabled(false);
YourMarkerView mv = new YourMarkerView(myActivity, R.layout.custom_marker_view);
// Set the marker to the chart
mv.setChartView(chart);
chart.setMarker(mv);
chart.setDragEnabled(false);
chart.setScaleEnabled(false);
// force pinch zoom along both axis
chart.setPinchZoom(false);
// enable touch gestures
chart.setTouchEnabled(true);
CombinedData data = new CombinedData();
data.setData(generateBarData());
data.setData(generateScatterData());
chart.setData(data);
chart.invalidate();
private BarData generateBarData() {
ArrayList<BarEntry> entries1 = new ArrayList<>();
ArrayList<BarEntry> entries2 = new ArrayList<>();
for (int index = 0; index < count; index++) {
entries1.add(new BarEntry(0, getRandom(25, 25)));
// stacked
entries2.add(new BarEntry(0, new float[]{getRandom(13, 12), getRandom(13, 12)}));
}
BarDataSet set1 = new BarDataSet(entries1, "Bar 1");
set1.setColor(Color.rgb(60, 220, 78));
set1.setValueTextColor(Color.rgb(60, 220, 78));
set1.setValueTextSize(10f);
set1.setAxisDependency(YAxis.AxisDependency.LEFT);
BarDataSet set2 = new BarDataSet(entries2, "");
set2.setStackLabels(new String[]{"Stack 1", "Stack 2"});
set2.setColors(Color.rgb(61, 165, 255), Color.rgb(23, 197, 255));
set2.setValueTextColor(Color.rgb(61, 165, 255));
set2.setValueTextSize(10f);
set2.setAxisDependency(YAxis.AxisDependency.LEFT);
float groupSpace = 0.06f;
float barSpace = 0.02f; // x2 dataset
float barWidth = 0.45f; // x2 dataset
// (0.45 + 0.02) * 2 + 0.06 = 1.00 -> interval per "group"
BarData d = new BarData(set1, set2);
d.setBarWidth(barWidth);
// make this BarData object grouped
d.groupBars(0, groupSpace, barSpace); // start at x = 0
return d;
}
private ScatterData generateScatterData() {
ScatterData d = new ScatterData();
ArrayList<Integer> colors = new ArrayList<Integer>();
for (String color : details.getSequenceColors()) {
colors.add(Color.parseColor(color));
}
ArrayList<Entry> entries = new ArrayList<>();
for (float index = 0; index < count; index += 0.5f)
entries.add(new Entry(index + 0.25f, getRandom(10, 55),"title;"+colors.get(index)));
ScatterDataSet set = new ScatterDataSet(entries, "Scatter DataSet");
set.setDrawHorizontalHighlightIndicator(false);
set.setDrawVerticalHighlightIndicator(false);
set.setColors(colors);
set.setScatterShape(ScatterChart.ScatterShape.CIRCLE);
set.setScatterShapeSize(20f);
set.setDrawValues(false);
set.setValueTextSize(10f);
d.addDataSet(set);
return d;
}
details.getSequenceColors is simple pojo contains the list of colors. For each point on Scatter Graph i am setting different colors. I am setting ScatterShape.CIRCLE color and Marker Background color same on Scatter Graph. As per Draw order I am drawing the bar graph first then the scatter one. Issue here i am facing is When i click on area where no scatter points exist the marker background color and nearest scatter point color is different and it highlights Bar graph datapoint as well. Its doesnt show the exact marker on Scatter points not sure why. How can i make sure that the scatter Circle color and marker Background color will be always in sync for each data points?
Solved by Using Custom ScatterDataSet Class:
public class MyScatterDataSet extends ScatterDataSet {
static int currentIndex = 0;
public MyScatterDataSet(List<Entry> yVals, String label) {
super(yVals, label);
}
#Override
public int getColor(int index) {
int ret =super.getColor(currentIndex);
currentIndex+=1;
return ret;
}
}
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;
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);
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.