1 2 package com.xxmassdeveloper.mpchartexample; 3 4 import android.Manifest; 5 import android.content.Intent; 6 import android.content.pm.PackageManager; 7 import android.graphics.Color; 8 import android.net.Uri; 9 import android.os.Bundle; 10 import androidx.core.content.ContextCompat; 11 import android.util.Log; 12 import android.view.Menu; 13 import android.view.MenuItem; 14 import android.view.WindowManager; 15 16 import com.github.mikephil.charting.charts.HorizontalBarChart; 17 import com.github.mikephil.charting.components.AxisBase; 18 import com.github.mikephil.charting.components.Legend; 19 import com.github.mikephil.charting.components.XAxis; 20 import com.github.mikephil.charting.components.XAxis.XAxisPosition; 21 import com.github.mikephil.charting.components.YAxis; 22 import com.github.mikephil.charting.data.BarData; 23 import com.github.mikephil.charting.data.BarDataSet; 24 import com.github.mikephil.charting.data.BarEntry; 25 import com.github.mikephil.charting.data.Entry; 26 import com.github.mikephil.charting.formatter.IValueFormatter; 27 import com.github.mikephil.charting.formatter.IAxisValueFormatter; 28 import com.github.mikephil.charting.highlight.Highlight; 29 import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; 30 import com.github.mikephil.charting.listener.OnChartValueSelectedListener; 31 import com.github.mikephil.charting.utils.ViewPortHandler; 32 import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; 33 34 import java.text.DecimalFormat; 35 import java.util.ArrayList; 36 import java.util.List; 37 38 public class StackedBarActivityNegative extends DemoBase implements 39 OnChartValueSelectedListener { 40 41 private HorizontalBarChart chart; 42 43 @Override onCreate(Bundle savedInstanceState)44 protected void onCreate(Bundle savedInstanceState) { 45 super.onCreate(savedInstanceState); 46 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 47 WindowManager.LayoutParams.FLAG_FULLSCREEN); 48 setContentView(R.layout.activity_age_distribution); 49 50 setTitle("StackedBarActivityNegative"); 51 52 chart = findViewById(R.id.chart1); 53 chart.setOnChartValueSelectedListener(this); 54 chart.setDrawGridBackground(false); 55 chart.getDescription().setEnabled(false); 56 57 // scaling can now only be done on x- and y-axis separately 58 chart.setPinchZoom(false); 59 60 chart.setDrawBarShadow(false); 61 chart.setDrawValueAboveBar(true); 62 chart.setHighlightFullBarEnabled(false); 63 64 chart.getAxisLeft().setEnabled(false); 65 chart.getAxisRight().setAxisMaximum(25f); 66 chart.getAxisRight().setAxisMinimum(-25f); 67 chart.getAxisRight().setDrawGridLines(false); 68 chart.getAxisRight().setDrawZeroLine(true); 69 chart.getAxisRight().setLabelCount(7, false); 70 chart.getAxisRight().setValueFormatter(new CustomFormatter()); 71 chart.getAxisRight().setTextSize(9f); 72 73 XAxis xAxis = chart.getXAxis(); 74 xAxis.setPosition(XAxisPosition.BOTH_SIDED); 75 xAxis.setDrawGridLines(false); 76 xAxis.setDrawAxisLine(false); 77 xAxis.setTextSize(9f); 78 xAxis.setAxisMinimum(0f); 79 xAxis.setAxisMaximum(110f); 80 xAxis.setCenterAxisLabels(true); 81 xAxis.setLabelCount(12); 82 xAxis.setGranularity(10f); 83 xAxis.setValueFormatter(new IAxisValueFormatter() { 84 85 private final DecimalFormat format = new DecimalFormat("###"); 86 87 @Override 88 public String getFormattedValue(float value, AxisBase axis) { 89 return format.format(value) + "-" + format.format(value + 10); 90 } 91 }); 92 93 Legend l = chart.getLegend(); 94 l.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM); 95 l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT); 96 l.setOrientation(Legend.LegendOrientation.HORIZONTAL); 97 l.setDrawInside(false); 98 l.setFormSize(8f); 99 l.setFormToTextSpace(4f); 100 l.setXEntrySpace(6f); 101 102 // IMPORTANT: When using negative values in stacked bars, always make sure the negative values are in the array first 103 ArrayList<BarEntry> values = new ArrayList<>(); 104 values.add(new BarEntry(5, new float[]{ -10, 10 })); 105 values.add(new BarEntry(15, new float[]{ -12, 13 })); 106 values.add(new BarEntry(25, new float[]{ -15, 15 })); 107 values.add(new BarEntry(35, new float[]{ -17, 17 })); 108 values.add(new BarEntry(45, new float[]{ -19, 20 })); 109 values.add(new BarEntry(45, new float[]{ -19, 20 }, getResources().getDrawable(R.drawable.star))); 110 values.add(new BarEntry(55, new float[]{ -19, 19 })); 111 values.add(new BarEntry(65, new float[]{ -16, 16 })); 112 values.add(new BarEntry(75, new float[]{ -13, 14 })); 113 values.add(new BarEntry(85, new float[]{ -10, 11 })); 114 values.add(new BarEntry(95, new float[]{ -5, 6 })); 115 values.add(new BarEntry(105, new float[]{ -1, 2 })); 116 117 BarDataSet set = new BarDataSet(values, "Age Distribution"); 118 set.setDrawIcons(false); 119 set.setValueFormatter(new CustomFormatter()); 120 set.setValueTextSize(7f); 121 set.setAxisDependency(YAxis.AxisDependency.RIGHT); 122 set.setColors(Color.rgb(67,67,72), Color.rgb(124,181,236)); 123 set.setStackLabels(new String[]{ 124 "Men", "Women" 125 }); 126 127 BarData data = new BarData(set); 128 data.setBarWidth(8.5f); 129 chart.setData(data); 130 chart.invalidate(); 131 } 132 133 @Override onCreateOptionsMenu(Menu menu)134 public boolean onCreateOptionsMenu(Menu menu) { 135 getMenuInflater().inflate(R.menu.bar, menu); 136 return true; 137 } 138 139 @Override onOptionsItemSelected(MenuItem item)140 public boolean onOptionsItemSelected(MenuItem item) { 141 142 switch (item.getItemId()) { 143 case R.id.viewGithub: { 144 Intent i = new Intent(Intent.ACTION_VIEW); 145 i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java")); 146 startActivity(i); 147 break; 148 } 149 case R.id.actionToggleValues: { 150 List<IBarDataSet> sets = chart.getData() 151 .getDataSets(); 152 153 for (IBarDataSet iSet : sets) { 154 155 BarDataSet set = (BarDataSet) iSet; 156 set.setDrawValues(!set.isDrawValuesEnabled()); 157 } 158 159 chart.invalidate(); 160 break; 161 } 162 case R.id.actionToggleIcons: { 163 List<IBarDataSet> sets = chart.getData() 164 .getDataSets(); 165 166 for (IBarDataSet iSet : sets) { 167 168 BarDataSet set = (BarDataSet) iSet; 169 set.setDrawIcons(!set.isDrawIconsEnabled()); 170 } 171 172 chart.invalidate(); 173 break; 174 } 175 case R.id.actionToggleHighlight: { 176 if(chart.getData() != null) { 177 chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled()); 178 chart.invalidate(); 179 } 180 break; 181 } 182 case R.id.actionTogglePinch: { 183 if (chart.isPinchZoomEnabled()) 184 chart.setPinchZoom(false); 185 else 186 chart.setPinchZoom(true); 187 188 chart.invalidate(); 189 break; 190 } 191 case R.id.actionToggleAutoScaleMinMax: { 192 chart.setAutoScaleMinMaxEnabled(!chart.isAutoScaleMinMaxEnabled()); 193 chart.notifyDataSetChanged(); 194 break; 195 } 196 case R.id.actionToggleBarBorders: { 197 for (IBarDataSet set : chart.getData().getDataSets()) 198 ((BarDataSet)set).setBarBorderWidth(set.getBarBorderWidth() == 1.f ? 0.f : 1.f); 199 200 chart.invalidate(); 201 break; 202 } 203 case R.id.animateX: { 204 chart.animateX(3000); 205 break; 206 } 207 case R.id.animateY: { 208 chart.animateY(3000); 209 break; 210 } 211 case R.id.animateXY: { 212 213 chart.animateXY(3000, 3000); 214 break; 215 } 216 case R.id.actionSave: { 217 if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { 218 saveToGallery(); 219 } else { 220 requestStoragePermission(chart); 221 } 222 break; 223 } 224 } 225 return true; 226 } 227 228 @Override saveToGallery()229 protected void saveToGallery() { 230 saveToGallery(chart, "StackedBarActivityNegative"); 231 } 232 233 @Override onValueSelected(Entry e, Highlight h)234 public void onValueSelected(Entry e, Highlight h) { 235 BarEntry entry = (BarEntry) e; 236 Log.i("VAL SELECTED", 237 "Value: " + Math.abs(entry.getYVals()[h.getStackIndex()])); 238 } 239 240 @Override onNothingSelected()241 public void onNothingSelected() { 242 Log.i("NOTING SELECTED", ""); 243 } 244 245 private class CustomFormatter implements IValueFormatter, IAxisValueFormatter { 246 247 private final DecimalFormat mFormat; 248 CustomFormatter()249 CustomFormatter() { 250 mFormat = new DecimalFormat("###"); 251 } 252 253 // data 254 @Override getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler)255 public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { 256 return mFormat.format(Math.abs(value)) + "m"; 257 } 258 259 // YAxis 260 @Override getFormattedValue(float value, AxisBase axis)261 public String getFormattedValue(float value, AxisBase axis) { 262 return mFormat.format(Math.abs(value)) + "m"; 263 } 264 } 265 } 266