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.RectF; 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.Legend; 21 import com.github.mikephil.charting.components.Legend.LegendForm; 22 import com.github.mikephil.charting.components.XAxis; 23 import com.github.mikephil.charting.components.XAxis.XAxisPosition; 24 import com.github.mikephil.charting.components.YAxis; 25 import com.github.mikephil.charting.components.YAxis.AxisDependency; 26 import com.github.mikephil.charting.components.YAxis.YAxisLabelPosition; 27 import com.github.mikephil.charting.data.BarData; 28 import com.github.mikephil.charting.data.BarDataSet; 29 import com.github.mikephil.charting.data.BarEntry; 30 import com.github.mikephil.charting.data.Entry; 31 import com.github.mikephil.charting.formatter.IAxisValueFormatter; 32 import com.github.mikephil.charting.highlight.Highlight; 33 import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; 34 import com.github.mikephil.charting.interfaces.datasets.IDataSet; 35 import com.github.mikephil.charting.listener.OnChartValueSelectedListener; 36 import com.github.mikephil.charting.utils.Fill; 37 import com.github.mikephil.charting.utils.MPPointF; 38 import com.xxmassdeveloper.mpchartexample.custom.DayAxisValueFormatter; 39 import com.xxmassdeveloper.mpchartexample.custom.MyAxisValueFormatter; 40 import com.xxmassdeveloper.mpchartexample.custom.XYMarkerView; 41 import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; 42 43 import java.util.ArrayList; 44 import java.util.List; 45 46 public class BarChartActivity extends DemoBase implements OnSeekBarChangeListener, 47 OnChartValueSelectedListener { 48 49 private BarChart chart; 50 private SeekBar seekBarX, seekBarY; 51 private TextView tvX, tvY; 52 53 @Override onCreate(Bundle savedInstanceState)54 protected void onCreate(Bundle savedInstanceState) { 55 super.onCreate(savedInstanceState); 56 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 57 WindowManager.LayoutParams.FLAG_FULLSCREEN); 58 setContentView(R.layout.activity_barchart); 59 60 setTitle("BarChartActivity"); 61 62 tvX = findViewById(R.id.tvXMax); 63 tvY = findViewById(R.id.tvYMax); 64 65 seekBarX = findViewById(R.id.seekBar1); 66 seekBarY = findViewById(R.id.seekBar2); 67 68 seekBarY.setOnSeekBarChangeListener(this); 69 seekBarX.setOnSeekBarChangeListener(this); 70 71 chart = findViewById(R.id.chart1); 72 chart.setOnChartValueSelectedListener(this); 73 74 chart.setDrawBarShadow(false); 75 chart.setDrawValueAboveBar(true); 76 77 chart.getDescription().setEnabled(false); 78 79 // if more than 60 entries are displayed in the chart, no values will be 80 // drawn 81 chart.setMaxVisibleValueCount(60); 82 83 // scaling can now only be done on x- and y-axis separately 84 chart.setPinchZoom(false); 85 86 chart.setDrawGridBackground(false); 87 // chart.setDrawYLabels(false); 88 89 IAxisValueFormatter xAxisFormatter = new DayAxisValueFormatter(chart); 90 91 XAxis xAxis = chart.getXAxis(); 92 xAxis.setPosition(XAxisPosition.BOTTOM); 93 xAxis.setTypeface(tfLight); 94 xAxis.setDrawGridLines(false); 95 xAxis.setGranularity(1f); // only intervals of 1 day 96 xAxis.setLabelCount(7); 97 xAxis.setValueFormatter(xAxisFormatter); 98 99 IAxisValueFormatter custom = new MyAxisValueFormatter(); 100 101 YAxis leftAxis = chart.getAxisLeft(); 102 leftAxis.setTypeface(tfLight); 103 leftAxis.setLabelCount(8, false); 104 leftAxis.setValueFormatter(custom); 105 leftAxis.setPosition(YAxisLabelPosition.OUTSIDE_CHART); 106 leftAxis.setSpaceTop(15f); 107 leftAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true) 108 109 YAxis rightAxis = chart.getAxisRight(); 110 rightAxis.setDrawGridLines(false); 111 rightAxis.setTypeface(tfLight); 112 rightAxis.setLabelCount(8, false); 113 rightAxis.setValueFormatter(custom); 114 rightAxis.setSpaceTop(15f); 115 rightAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true) 116 117 Legend l = chart.getLegend(); 118 l.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM); 119 l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.LEFT); 120 l.setOrientation(Legend.LegendOrientation.HORIZONTAL); 121 l.setDrawInside(false); 122 l.setForm(LegendForm.SQUARE); 123 l.setFormSize(9f); 124 l.setTextSize(11f); 125 l.setXEntrySpace(4f); 126 127 XYMarkerView mv = new XYMarkerView(this, xAxisFormatter); 128 mv.setChartView(chart); // For bounds control 129 chart.setMarker(mv); // Set the marker to the chart 130 131 // setting data 132 seekBarY.setProgress(50); 133 seekBarX.setProgress(12); 134 135 // chart.setDrawLegend(false); 136 } 137 setData(int count, float range)138 private void setData(int count, float range) { 139 140 float start = 1f; 141 142 ArrayList<BarEntry> values = new ArrayList<>(); 143 144 for (int i = (int) start; i < start + count; i++) { 145 float val = (float) (Math.random() * (range + 1)); 146 147 if (Math.random() * 100 < 25) { 148 values.add(new BarEntry(i, val, getResources().getDrawable(R.drawable.star))); 149 } else { 150 values.add(new BarEntry(i, val)); 151 } 152 } 153 154 BarDataSet set1; 155 156 if (chart.getData() != null && 157 chart.getData().getDataSetCount() > 0) { 158 set1 = (BarDataSet) chart.getData().getDataSetByIndex(0); 159 set1.setValues(values); 160 chart.getData().notifyDataChanged(); 161 chart.notifyDataSetChanged(); 162 163 } else { 164 set1 = new BarDataSet(values, "The year 2017"); 165 166 set1.setDrawIcons(false); 167 168 int startColor1 = ContextCompat.getColor(this, android.R.color.holo_orange_light); 169 int startColor2 = ContextCompat.getColor(this, android.R.color.holo_blue_light); 170 int startColor3 = ContextCompat.getColor(this, android.R.color.holo_orange_light); 171 int startColor4 = ContextCompat.getColor(this, android.R.color.holo_green_light); 172 int startColor5 = ContextCompat.getColor(this, android.R.color.holo_red_light); 173 int endColor1 = ContextCompat.getColor(this, android.R.color.holo_blue_dark); 174 int endColor2 = ContextCompat.getColor(this, android.R.color.holo_purple); 175 int endColor3 = ContextCompat.getColor(this, android.R.color.holo_green_dark); 176 int endColor4 = ContextCompat.getColor(this, android.R.color.holo_red_dark); 177 int endColor5 = ContextCompat.getColor(this, android.R.color.holo_orange_dark); 178 179 List<Fill> gradientFills = new ArrayList<>(); 180 gradientFills.add(new Fill(startColor1, endColor1)); 181 gradientFills.add(new Fill(startColor2, endColor2)); 182 gradientFills.add(new Fill(startColor3, endColor3)); 183 gradientFills.add(new Fill(startColor4, endColor4)); 184 gradientFills.add(new Fill(startColor5, endColor5)); 185 186 set1.setFills(gradientFills); 187 188 ArrayList<IBarDataSet> dataSets = new ArrayList<>(); 189 dataSets.add(set1); 190 191 BarData data = new BarData(dataSets); 192 data.setValueTextSize(10f); 193 data.setValueTypeface(tfLight); 194 data.setBarWidth(0.9f); 195 196 chart.setData(data); 197 } 198 } 199 200 @Override onCreateOptionsMenu(Menu menu)201 public boolean onCreateOptionsMenu(Menu menu) { 202 getMenuInflater().inflate(R.menu.bar, menu); 203 return true; 204 } 205 206 @Override onOptionsItemSelected(MenuItem item)207 public boolean onOptionsItemSelected(MenuItem item) { 208 209 switch (item.getItemId()) { 210 case R.id.viewGithub: { 211 Intent i = new Intent(Intent.ACTION_VIEW); 212 i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java")); 213 startActivity(i); 214 break; 215 } 216 case R.id.actionToggleValues: { 217 for (IDataSet set : chart.getData().getDataSets()) 218 set.setDrawValues(!set.isDrawValuesEnabled()); 219 220 chart.invalidate(); 221 break; 222 } 223 case R.id.actionToggleIcons: { 224 for (IDataSet set : chart.getData().getDataSets()) 225 set.setDrawIcons(!set.isDrawIconsEnabled()); 226 227 chart.invalidate(); 228 break; 229 } 230 case R.id.actionToggleHighlight: { 231 if (chart.getData() != null) { 232 chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled()); 233 chart.invalidate(); 234 } 235 break; 236 } 237 case R.id.actionTogglePinch: { 238 if (chart.isPinchZoomEnabled()) 239 chart.setPinchZoom(false); 240 else 241 chart.setPinchZoom(true); 242 243 chart.invalidate(); 244 break; 245 } 246 case R.id.actionToggleAutoScaleMinMax: { 247 chart.setAutoScaleMinMaxEnabled(!chart.isAutoScaleMinMaxEnabled()); 248 chart.notifyDataSetChanged(); 249 break; 250 } 251 case R.id.actionToggleBarBorders: { 252 for (IBarDataSet set : chart.getData().getDataSets()) 253 ((BarDataSet) set).setBarBorderWidth(set.getBarBorderWidth() == 1.f ? 0.f : 1.f); 254 255 chart.invalidate(); 256 break; 257 } 258 case R.id.animateX: { 259 chart.animateX(2000); 260 break; 261 } 262 case R.id.animateY: { 263 chart.animateY(2000); 264 break; 265 } 266 case R.id.animateXY: { 267 chart.animateXY(2000, 2000); 268 break; 269 } 270 case R.id.actionSave: { 271 if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { 272 saveToGallery(); 273 } else { 274 requestStoragePermission(chart); 275 } 276 break; 277 } 278 } 279 return true; 280 } 281 282 @Override onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)283 public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 284 285 tvX.setText(String.valueOf(seekBarX.getProgress())); 286 tvY.setText(String.valueOf(seekBarY.getProgress())); 287 288 setData(seekBarX.getProgress(), seekBarY.getProgress()); 289 chart.invalidate(); 290 } 291 292 @Override saveToGallery()293 protected void saveToGallery() { 294 saveToGallery(chart, "BarChartActivity"); 295 } 296 297 @Override onStartTrackingTouch(SeekBar seekBar)298 public void onStartTrackingTouch(SeekBar seekBar) {} 299 300 @Override onStopTrackingTouch(SeekBar seekBar)301 public void onStopTrackingTouch(SeekBar seekBar) {} 302 303 private final RectF onValueSelectedRectF = new RectF(); 304 305 @Override onValueSelected(Entry e, Highlight h)306 public void onValueSelected(Entry e, Highlight h) { 307 308 if (e == null) 309 return; 310 311 RectF bounds = onValueSelectedRectF; 312 chart.getBarBounds((BarEntry) e, bounds); 313 MPPointF position = chart.getPosition(e, AxisDependency.LEFT); 314 315 Log.i("bounds", bounds.toString()); 316 Log.i("position", position.toString()); 317 318 Log.i("x-index", 319 "low: " + chart.getLowestVisibleX() + ", high: " 320 + chart.getHighestVisibleX()); 321 322 MPPointF.recycleInstance(position); 323 } 324 325 @Override onNothingSelected()326 public void onNothingSelected() { } 327 } 328