1 package com.xxmassdeveloper.mpchartexample;
2 
3 import android.Manifest;
4 import android.content.Intent;
5 import android.content.pm.PackageManager;
6 import android.graphics.Color;
7 import android.net.Uri;
8 import android.os.Bundle;
9 import androidx.core.content.ContextCompat;
10 import android.util.Log;
11 import android.view.Menu;
12 import android.view.MenuItem;
13 import android.view.WindowManager;
14 import android.widget.SeekBar;
15 import android.widget.SeekBar.OnSeekBarChangeListener;
16 import android.widget.TextView;
17 
18 import com.github.mikephil.charting.charts.BarChart;
19 import com.github.mikephil.charting.components.Legend;
20 import com.github.mikephil.charting.components.XAxis;
21 import com.github.mikephil.charting.components.XAxis.XAxisPosition;
22 import com.github.mikephil.charting.components.YAxis;
23 import com.github.mikephil.charting.data.BarData;
24 import com.github.mikephil.charting.data.BarDataSet;
25 import com.github.mikephil.charting.data.BarEntry;
26 import com.github.mikephil.charting.data.Entry;
27 import com.github.mikephil.charting.highlight.Highlight;
28 import com.github.mikephil.charting.interfaces.datasets.IBarDataSet;
29 import com.github.mikephil.charting.listener.OnChartValueSelectedListener;
30 import com.github.mikephil.charting.utils.ColorTemplate;
31 import com.xxmassdeveloper.mpchartexample.custom.MyAxisValueFormatter;
32 import com.xxmassdeveloper.mpchartexample.custom.MyValueFormatter;
33 import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase;
34 
35 import java.util.ArrayList;
36 import java.util.List;
37 
38 public class StackedBarActivity extends DemoBase implements OnSeekBarChangeListener, OnChartValueSelectedListener {
39 
40     private BarChart chart;
41     private SeekBar seekBarX, seekBarY;
42     private TextView tvX, tvY;
43 
44     @Override
onCreate(Bundle savedInstanceState)45     protected void onCreate(Bundle savedInstanceState) {
46         super.onCreate(savedInstanceState);
47         getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
48         setContentView(R.layout.activity_barchart);
49 
50         setTitle("StackedBarActivity");
51 
52         tvX = findViewById(R.id.tvXMax);
53         tvY = findViewById(R.id.tvYMax);
54 
55         seekBarX = findViewById(R.id.seekBar1);
56         seekBarX.setOnSeekBarChangeListener(this);
57 
58         seekBarY = findViewById(R.id.seekBar2);
59         seekBarY.setOnSeekBarChangeListener(this);
60 
61         chart = findViewById(R.id.chart1);
62         chart.setOnChartValueSelectedListener(this);
63 
64         chart.getDescription().setEnabled(false);
65 
66         // if more than 60 entries are displayed in the chart, no values will be
67         // drawn
68         chart.setMaxVisibleValueCount(40);
69 
70         // scaling can now only be done on x- and y-axis separately
71         chart.setPinchZoom(false);
72 
73         chart.setDrawGridBackground(false);
74         chart.setDrawBarShadow(false);
75 
76         chart.setDrawValueAboveBar(false);
77         chart.setHighlightFullBarEnabled(false);
78 
79         // change the position of the y-labels
80         YAxis leftAxis = chart.getAxisLeft();
81         leftAxis.setValueFormatter(new MyAxisValueFormatter());
82         leftAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true)
83         chart.getAxisRight().setEnabled(false);
84 
85         XAxis xLabels = chart.getXAxis();
86         xLabels.setPosition(XAxisPosition.TOP);
87 
88         // chart.setDrawXLabels(false);
89         // chart.setDrawYLabels(false);
90 
91         // setting data
92         seekBarX.setProgress(12);
93         seekBarY.setProgress(100);
94 
95         Legend l = chart.getLegend();
96         l.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM);
97         l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT);
98         l.setOrientation(Legend.LegendOrientation.HORIZONTAL);
99         l.setDrawInside(false);
100         l.setFormSize(8f);
101         l.setFormToTextSpace(4f);
102         l.setXEntrySpace(6f);
103 
104         // chart.setDrawLegend(false);
105     }
106 
107     @Override
onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)108     public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
109 
110         tvX.setText(String.valueOf(seekBarX.getProgress()));
111         tvY.setText(String.valueOf(seekBarY.getProgress()));
112 
113         ArrayList<BarEntry> values = new ArrayList<>();
114 
115         for (int i = 0; i < seekBarX.getProgress(); i++) {
116             float mul = (seekBarY.getProgress() + 1);
117             float val1 = (float) (Math.random() * mul) + mul / 3;
118             float val2 = (float) (Math.random() * mul) + mul / 3;
119             float val3 = (float) (Math.random() * mul) + mul / 3;
120 
121             values.add(new BarEntry(
122                     i,
123                     new float[]{val1, val2, val3},
124                     getResources().getDrawable(R.drawable.star)));
125         }
126 
127         BarDataSet set1;
128 
129         if (chart.getData() != null &&
130                 chart.getData().getDataSetCount() > 0) {
131             set1 = (BarDataSet) chart.getData().getDataSetByIndex(0);
132             set1.setValues(values);
133             chart.getData().notifyDataChanged();
134             chart.notifyDataSetChanged();
135         } else {
136             set1 = new BarDataSet(values, "Statistics Vienna 2014");
137             set1.setDrawIcons(false);
138             set1.setColors(getColors());
139             set1.setStackLabels(new String[]{"Births", "Divorces", "Marriages"});
140 
141             ArrayList<IBarDataSet> dataSets = new ArrayList<>();
142             dataSets.add(set1);
143 
144             BarData data = new BarData(dataSets);
145             data.setValueFormatter(new MyValueFormatter());
146             data.setValueTextColor(Color.WHITE);
147 
148             chart.setData(data);
149         }
150 
151         chart.setFitBars(true);
152         chart.invalidate();
153     }
154 
155     @Override
onCreateOptionsMenu(Menu menu)156     public boolean onCreateOptionsMenu(Menu menu) {
157         getMenuInflater().inflate(R.menu.bar, menu);
158         return true;
159     }
160 
161     @Override
onOptionsItemSelected(MenuItem item)162     public boolean onOptionsItemSelected(MenuItem item) {
163 
164         switch (item.getItemId()) {
165             case R.id.viewGithub: {
166                 Intent i = new Intent(Intent.ACTION_VIEW);
167                 i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java"));
168                 startActivity(i);
169                 break;
170             }
171             case R.id.actionToggleValues: {
172                 List<IBarDataSet> sets = chart.getData()
173                         .getDataSets();
174 
175                 for (IBarDataSet iSet : sets) {
176 
177                     BarDataSet set = (BarDataSet) iSet;
178                     set.setDrawValues(!set.isDrawValuesEnabled());
179                 }
180 
181                 chart.invalidate();
182                 break;
183             }
184             case R.id.actionToggleIcons: {
185                 List<IBarDataSet> sets = chart.getData()
186                         .getDataSets();
187 
188                 for (IBarDataSet iSet : sets) {
189 
190                     BarDataSet set = (BarDataSet) iSet;
191                     set.setDrawIcons(!set.isDrawIconsEnabled());
192                 }
193 
194                 chart.invalidate();
195                 break;
196             }
197             case R.id.actionToggleHighlight: {
198                 if (chart.getData() != null) {
199                     chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled());
200                     chart.invalidate();
201                 }
202                 break;
203             }
204             case R.id.actionTogglePinch: {
205                 if (chart.isPinchZoomEnabled())
206                     chart.setPinchZoom(false);
207                 else
208                     chart.setPinchZoom(true);
209 
210                 chart.invalidate();
211                 break;
212             }
213             case R.id.actionToggleAutoScaleMinMax: {
214                 chart.setAutoScaleMinMaxEnabled(!chart.isAutoScaleMinMaxEnabled());
215                 chart.notifyDataSetChanged();
216                 break;
217             }
218             case R.id.actionToggleBarBorders: {
219                 for (IBarDataSet set : chart.getData().getDataSets())
220                     ((BarDataSet) set).setBarBorderWidth(set.getBarBorderWidth() == 1.f ? 0.f : 1.f);
221 
222                 chart.invalidate();
223                 break;
224             }
225             case R.id.animateX: {
226                 chart.animateX(2000);
227                 break;
228             }
229             case R.id.animateY: {
230                 chart.animateY(2000);
231                 break;
232             }
233             case R.id.animateXY: {
234 
235                 chart.animateXY(2000, 2000);
236                 break;
237             }
238             case R.id.actionSave: {
239                 if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
240                     saveToGallery();
241                 } else {
242                     requestStoragePermission(chart);
243                 }
244                 break;
245             }
246         }
247         return true;
248     }
249 
250     @Override
saveToGallery()251     protected void saveToGallery() {
252         saveToGallery(chart, "StackedBarActivity");
253     }
254 
255     @Override
onStartTrackingTouch(SeekBar seekBar)256     public void onStartTrackingTouch(SeekBar seekBar) {}
257 
258     @Override
onStopTrackingTouch(SeekBar seekBar)259     public void onStopTrackingTouch(SeekBar seekBar) {}
260 
261     @Override
onValueSelected(Entry e, Highlight h)262     public void onValueSelected(Entry e, Highlight h) {
263 
264         BarEntry entry = (BarEntry) e;
265 
266         if (entry.getYVals() != null)
267             Log.i("VAL SELECTED", "Value: " + entry.getYVals()[h.getStackIndex()]);
268         else
269             Log.i("VAL SELECTED", "Value: " + entry.getY());
270     }
271 
272     @Override
onNothingSelected()273     public void onNothingSelected() {}
274 
getColors()275     private int[] getColors() {
276 
277         // have as many colors as stack-values per entry
278         int[] colors = new int[3];
279 
280         System.arraycopy(ColorTemplate.MATERIAL_COLORS, 0, colors, 0, 3);
281 
282         return colors;
283     }
284 }
285