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 import android.widget.SeekBar; 16 import android.widget.SeekBar.OnSeekBarChangeListener; 17 import android.widget.TextView; 18 19 import com.github.mikephil.charting.charts.BarChart; 20 import com.github.mikephil.charting.components.AxisBase; 21 import com.github.mikephil.charting.components.Legend; 22 import com.github.mikephil.charting.components.XAxis; 23 import com.github.mikephil.charting.components.YAxis; 24 import com.github.mikephil.charting.data.BarData; 25 import com.github.mikephil.charting.data.BarDataSet; 26 import com.github.mikephil.charting.data.BarEntry; 27 import com.github.mikephil.charting.data.Entry; 28 import com.github.mikephil.charting.formatter.IAxisValueFormatter; 29 import com.github.mikephil.charting.formatter.LargeValueFormatter; 30 import com.github.mikephil.charting.highlight.Highlight; 31 import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; 32 import com.github.mikephil.charting.listener.OnChartValueSelectedListener; 33 import com.xxmassdeveloper.mpchartexample.custom.MyMarkerView; 34 import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; 35 36 import java.util.ArrayList; 37 import java.util.Locale; 38 39 public class BarChartActivityMultiDataset extends DemoBase implements OnSeekBarChangeListener, 40 OnChartValueSelectedListener { 41 42 private BarChart chart; 43 private SeekBar seekBarX, seekBarY; 44 private TextView tvX, tvY; 45 46 @Override onCreate(Bundle savedInstanceState)47 protected void onCreate(Bundle savedInstanceState) { 48 super.onCreate(savedInstanceState); 49 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 50 WindowManager.LayoutParams.FLAG_FULLSCREEN); 51 setContentView(R.layout.activity_barchart); 52 53 setTitle("BarChartActivityMultiDataset"); 54 55 tvX = findViewById(R.id.tvXMax); 56 tvX.setTextSize(10); 57 tvY = findViewById(R.id.tvYMax); 58 59 seekBarX = findViewById(R.id.seekBar1); 60 seekBarX.setMax(50); 61 seekBarX.setOnSeekBarChangeListener(this); 62 63 seekBarY = findViewById(R.id.seekBar2); 64 seekBarY.setOnSeekBarChangeListener(this); 65 66 chart = findViewById(R.id.chart1); 67 chart.setOnChartValueSelectedListener(this); 68 chart.getDescription().setEnabled(false); 69 70 // chart.setDrawBorders(true); 71 72 // scaling can now only be done on x- and y-axis separately 73 chart.setPinchZoom(false); 74 75 chart.setDrawBarShadow(false); 76 77 chart.setDrawGridBackground(false); 78 79 // create a custom MarkerView (extend MarkerView) and specify the layout 80 // to use for it 81 MyMarkerView mv = new MyMarkerView(this, R.layout.custom_marker_view); 82 mv.setChartView(chart); // For bounds control 83 chart.setMarker(mv); // Set the marker to the chart 84 85 seekBarX.setProgress(10); 86 seekBarY.setProgress(100); 87 88 Legend l = chart.getLegend(); 89 l.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP); 90 l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT); 91 l.setOrientation(Legend.LegendOrientation.VERTICAL); 92 l.setDrawInside(true); 93 l.setTypeface(tfLight); 94 l.setYOffset(0f); 95 l.setXOffset(10f); 96 l.setYEntrySpace(0f); 97 l.setTextSize(8f); 98 99 XAxis xAxis = chart.getXAxis(); 100 xAxis.setTypeface(tfLight); 101 xAxis.setGranularity(1f); 102 xAxis.setCenterAxisLabels(true); 103 xAxis.setValueFormatter(new IAxisValueFormatter() { 104 @Override 105 public String getFormattedValue(float value, AxisBase axis) { 106 return String.valueOf((int) value); 107 } 108 }); 109 110 YAxis leftAxis = chart.getAxisLeft(); 111 leftAxis.setTypeface(tfLight); 112 leftAxis.setValueFormatter(new LargeValueFormatter()); 113 leftAxis.setDrawGridLines(false); 114 leftAxis.setSpaceTop(35f); 115 leftAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true) 116 117 chart.getAxisRight().setEnabled(false); 118 } 119 120 @Override onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)121 public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 122 123 float groupSpace = 0.08f; 124 float barSpace = 0.03f; // x4 DataSet 125 float barWidth = 0.2f; // x4 DataSet 126 // (0.2 + 0.03) * 4 + 0.08 = 1.00 -> interval per "group" 127 128 int groupCount = seekBarX.getProgress() + 1; 129 int startYear = 1980; 130 int endYear = startYear + groupCount; 131 132 tvX.setText(String.format(Locale.ENGLISH, "%d-%d", startYear, endYear)); 133 tvY.setText(String.valueOf(seekBarY.getProgress())); 134 135 ArrayList<BarEntry> values1 = new ArrayList<>(); 136 ArrayList<BarEntry> values2 = new ArrayList<>(); 137 ArrayList<BarEntry> values3 = new ArrayList<>(); 138 ArrayList<BarEntry> values4 = new ArrayList<>(); 139 140 float randomMultiplier = seekBarY.getProgress() * 100000f; 141 142 for (int i = startYear; i < endYear; i++) { 143 values1.add(new BarEntry(i, (float) (Math.random() * randomMultiplier))); 144 values2.add(new BarEntry(i, (float) (Math.random() * randomMultiplier))); 145 values3.add(new BarEntry(i, (float) (Math.random() * randomMultiplier))); 146 values4.add(new BarEntry(i, (float) (Math.random() * randomMultiplier))); 147 } 148 149 BarDataSet set1, set2, set3, set4; 150 151 if (chart.getData() != null && chart.getData().getDataSetCount() > 0) { 152 153 set1 = (BarDataSet) chart.getData().getDataSetByIndex(0); 154 set2 = (BarDataSet) chart.getData().getDataSetByIndex(1); 155 set3 = (BarDataSet) chart.getData().getDataSetByIndex(2); 156 set4 = (BarDataSet) chart.getData().getDataSetByIndex(3); 157 set1.setValues(values1); 158 set2.setValues(values2); 159 set3.setValues(values3); 160 set4.setValues(values4); 161 chart.getData().notifyDataChanged(); 162 chart.notifyDataSetChanged(); 163 164 } else { 165 // create 4 DataSets 166 set1 = new BarDataSet(values1, "Company A"); 167 set1.setColor(Color.rgb(104, 241, 175)); 168 set2 = new BarDataSet(values2, "Company B"); 169 set2.setColor(Color.rgb(164, 228, 251)); 170 set3 = new BarDataSet(values3, "Company C"); 171 set3.setColor(Color.rgb(242, 247, 158)); 172 set4 = new BarDataSet(values4, "Company D"); 173 set4.setColor(Color.rgb(255, 102, 0)); 174 175 BarData data = new BarData(set1, set2, set3, set4); 176 data.setValueFormatter(new LargeValueFormatter()); 177 data.setValueTypeface(tfLight); 178 179 chart.setData(data); 180 } 181 182 // specify the width each bar should have 183 chart.getBarData().setBarWidth(barWidth); 184 185 // restrict the x-axis range 186 chart.getXAxis().setAxisMinimum(startYear); 187 188 // barData.getGroupWith(...) is a helper that calculates the width each group needs based on the provided parameters 189 chart.getXAxis().setAxisMaximum(startYear + chart.getBarData().getGroupWidth(groupSpace, barSpace) * groupCount); 190 chart.groupBars(startYear, groupSpace, barSpace); 191 chart.invalidate(); 192 } 193 194 @Override onCreateOptionsMenu(Menu menu)195 public boolean onCreateOptionsMenu(Menu menu) { 196 getMenuInflater().inflate(R.menu.bar, menu); 197 return true; 198 } 199 200 @Override onOptionsItemSelected(MenuItem item)201 public boolean onOptionsItemSelected(MenuItem item) { 202 203 switch (item.getItemId()) { 204 case R.id.viewGithub: { 205 Intent i = new Intent(Intent.ACTION_VIEW); 206 i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java")); 207 startActivity(i); 208 break; 209 } 210 case R.id.actionToggleValues: { 211 for (IBarDataSet set : chart.getData().getDataSets()) 212 set.setDrawValues(!set.isDrawValuesEnabled()); 213 214 chart.invalidate(); 215 break; 216 } 217 case R.id.actionTogglePinch: { 218 if (chart.isPinchZoomEnabled()) 219 chart.setPinchZoom(false); 220 else 221 chart.setPinchZoom(true); 222 223 chart.invalidate(); 224 break; 225 } 226 case R.id.actionToggleAutoScaleMinMax: { 227 chart.setAutoScaleMinMaxEnabled(!chart.isAutoScaleMinMaxEnabled()); 228 chart.notifyDataSetChanged(); 229 break; 230 } 231 case R.id.actionToggleBarBorders: { 232 for (IBarDataSet set : chart.getData().getDataSets()) 233 ((BarDataSet) set).setBarBorderWidth(set.getBarBorderWidth() == 1.f ? 0.f : 1.f); 234 235 chart.invalidate(); 236 break; 237 } 238 case R.id.actionToggleHighlight: { 239 if (chart.getData() != null) { 240 chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled()); 241 chart.invalidate(); 242 } 243 break; 244 } 245 case R.id.actionSave: { 246 if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { 247 saveToGallery(); 248 } else { 249 requestStoragePermission(chart); 250 } 251 break; 252 } 253 case R.id.animateX: { 254 chart.animateX(2000); 255 break; 256 } 257 case R.id.animateY: { 258 chart.animateY(2000); 259 break; 260 } 261 case R.id.animateXY: { 262 chart.animateXY(2000, 2000); 263 break; 264 } 265 } 266 return true; 267 } 268 269 @Override saveToGallery()270 protected void saveToGallery() { 271 saveToGallery(chart, "BarChartActivityMultiDataset"); 272 } 273 274 @Override onStartTrackingTouch(SeekBar seekBar)275 public void onStartTrackingTouch(SeekBar seekBar) {} 276 277 @Override onStopTrackingTouch(SeekBar seekBar)278 public void onStopTrackingTouch(SeekBar seekBar) {} 279 280 @Override onValueSelected(Entry e, Highlight h)281 public void onValueSelected(Entry e, Highlight h) { 282 Log.i("Activity", "Selected: " + e.toString() + ", dataSet: " + h.getDataSetIndex()); 283 } 284 285 @Override onNothingSelected()286 public void onNothingSelected() { 287 Log.i("Activity", "Nothing selected."); 288 } 289 } 290