How to display available and unavailable slots in a horizontal bar graph in android

Issue

I am trying to display the available and unavailable slots on a horizontal bar graph, but not able to find a solution to that. The values coming from server are like this:

start_time - 9.30am
end_time - 11.30am
status - available

start_time - 11.30am
end_time - 12.00pm
status - available

start_time - 12.00pm
end_time - 15.00pm
status - not available

[and so on... till 21.00pm]

So I have to represent the available slots with green color and unavailable slots with grey color on a single horizontal bar. Presently, I am using horizontal bar graph of MP Chart Android but it is not giving me the desired result.

Here is the image of what I want to achieve:

Here is the code I am using:

int StockColors[] = new int[]{Color.parseColor("#24E224"), Color.parseColor("#A9A9A9")};

                    ArrayList<BarEntry> entries = new ArrayList<>();
                    entries.add(new BarEntry(0f, arr));
                    BarDataSet bardataset = new BarDataSet(entries, "");
                    bardataset.setColors(StockColors);
                    bardataset.setDrawValues(false);
                    stockChart.getAxisRight().setCenterAxisLabels(true);
                    BarData data = new BarData(bardataset);
                    data.setBarWidth(5f);

                    Legend legend = stockChart.getLegend();

                    LegendEntry legendentry1 = new LegendEntry();
                    legendentry1.label = "Available Slot";
                    legendentry1.formColor = Color.GREEN;

                    LegendEntry legendentry2 = new LegendEntry();
                    legendentry2.label = "UnAvailable Slot";
                    legendentry2.formColor = Color.GRAY;

                    legend.setCustom(Arrays.asList(legendentry1, legendentry2));

                    stockChart.setExtraBottomOffset(20f);
                    stockChart.getLegend().setXEntrySpace(30f);
                    stockChart.getLegend().setYEntrySpace(20f);
                    stockChart.getAxisRight().setDrawGridLines(false);
                    stockChart.getAxisRight().setDrawAxisLine(false);
                    stockChart.getAxisRight().setGranularity(1f);

                    stockChart.setViewPortOffsets(0f, 0f, 0f, 0f);
                    stockChart.setExtraOffsets(0f, 0f, 0f, 0f);

                    stockChart.getAxisLeft().setEnabled(false); //show y-axis at left
                    stockChart.getAxisRight().setEnabled(true); //hide y-axis at right

                    stockChart.setScaleEnabled(false);
                    stockChart.getAxisRight().setEnabled(true);
                    stockChart.getXAxis().setEnabled(false);
                    stockChart.getXAxis().setDrawAxisLine(false);

                    stockChart.setData(data);
                    stockChart.getAxisRight().setTextColor(Color.WHITE);
                    stockChart.getXAxis().setTextColor(Color.WHITE);
                    stockChart.getLegend().setTextColor(Color.WHITE);

                    stockChart.getDescription().setEnabled(false);
                    stockChart.setFitBars(false);
                    stockChart.setTouchEnabled(true);

                    stockChart.setDrawGridBackground(false);
                    stockChart.setDrawBarShadow(false);
                    stockChart.setDrawValueAboveBar(false);
                    stockChart.invalidate();

                    xvalues = new ArrayList<>();
                    xvalues.add("9.00");
                    xvalues.add("10.00");
                    xvalues.add("11.00");
                    xvalues.add("12.00");
                    xvalues.add("13.00");
                    xvalues.add("14.00");
                    xvalues.add("15.00");
                    xvalues.add("16.00");
                    xvalues.add("17.00");
                    xvalues.add("18.00");
                    xvalues.add("19.00");
                    xvalues.add("20.00");
                    xvalues.add("21.00");

                    stockChart.getAxisRight().setLabelCount(xvalues.size()+3, true); // also if i use entries.size() here, then only few labels are visible
                    stockChart.getAxisRight().setDrawLabels(true);

stockChart.getAxisRight().setValueFormatter(new newBarChartXaxisFormatter());


public class newBarChartXaxisFormatter implements IAxisValueFormatter
    {
        @SuppressLint("StringFormatInvalid")
        @Override
        public String getFormattedValue(float value, AxisBase axis) {
            int a = (int) (10f + value); // if i use 9f then it starts with 7
            return String.valueOf(a);
        }
    }

This is the current result with the code above:
Image of what i am getting with using the above code

Solution

The correct way of achieving the above graph is using Stacked Bar graph and HorizontalBarChart component of MpAndroidChart

sample output image

Note: I will be linking the project with the sample output shown in the above diagram. Check the comments section for the link.
Run HorizontalStackedBarGraph.kt activity to try the solution. The code written below is commented to give you an idea as to how you can implement it in your project.

Paste the above code in your activity XML

<com.github.mikephil.charting.charts.HorizontalBarChart
    android:id="@+id/timetable_barchart"
    android:layout_marginBottom="40dp"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

class HorizontalStackedBarGraph : AppCompatActivity() {

val startTime = 9f
val EXTRA_GRAPH_SIZE = 3
// In Horizontal graph Bar width will set your graph height.
val BAR_WIDTH = 0.3F
// Calculate the time interval and create an array
val entries = floatArrayOf(2f, 1f, 3f, 3f, 1f, 2f) 

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_horizontal_stacked_bar_graph)

    val barChart = findViewById<BarChart>(R.id.timetable_barchart);
    
    // Add the list of values to a single BarEntry
    val timeTableEntries = BarEntry(0f, entries)
    val set1 = BarDataSet(listOf(timeTableEntries), "TimeTable")
    set1.setColors(intArrayOf(R.color.colorAvailableSlot, R.color.colorUnAvailableSlot), this)
    set1.setDrawValues(false)
    val barData = BarData(set1)
    barData.barWidth = BAR_WIDTH
    barChart.data = barData
    barChart.description.isEnabled = false
    
    val legend1= LegendEntry().apply {
        formColor = ContextCompat.getColor([email protected], R.color.colorAvailableSlot)
        label = "Unavailable Slot"
    }
    
    val legend2= LegendEntry().apply {
        formColor = ContextCompat.getColor([email protected], R.color.colorUnAvailableSlot)
        label = "Available Slot"
    }

    val valueFormatterForTime = object : ValueFormatter() {
        override fun getFormattedValue(value: Float): String {
            return getString(R.string.time, (startTime + value).toInt())
        }
    }

    //Bar graph customization
    barChart.extraBottomOffset = 20f
    barChart.legend.xEntrySpace = 10f
    barChart.legend.setCustom(arrayListOf(legend1, legend2))
    barChart.axisRight.apply {
        setDrawGridLines(false)
        granularity = 1f
        valueFormatter = valueFormatterForTime
        labelCount = entries.size + EXTRA_GRAPH_SIZE
    }
    barChart.axisLeft.isEnabled = false
    barChart.xAxis.isEnabled = false
    barChart.xAxis.axisMinimum = 0f
    barChart.setDrawGridBackground(false)
    barChart.setDrawBarShadow(false)
    barChart.setDrawValueAboveBar(false)
    barChart.invalidate()
    }
}

Answered By – Extremis II

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published